Olga Grabek

Olga Grabek Senior Software
Engineer

Temat: HashMap i zliczanie występujących wartości.

Mam do napisania następujący program: użytkownik podaje napisy . Program ma na wyjściu zliczyć powtarzająca się napisy, czyli podać np. coś takiego: ala 3, ewa 2, janek 1.

Mam przy tym użyć HashMap. Możecie coś podpowiedzieć?

Na razie mam coś takiego:

public static void main(String[] args) {
// pobranie napisów wprowadzonych do wiersza poleceń
String dane = JOptionPane.showInputDialog("Podaj napisy oddzielone przecinkami");
final String REGEX = ",";
Pattern p = Pattern.compile(REGEX);
String[] items = p.split(dane);
HashMap map = new HashMap();

i dalej ładuje to co mam w tablicy items za pomocą pętli do HashMap(nie wiem dlaczego ale ucina mi ten fragment kodu jak go wpisuje do posta)Olga Grabek edytował(a) ten post dnia 22.12.08 o godzinie 20:00
Michał Rojek

Michał Rojek Programista J2EE,
CoreTeam

Temat: HashMap i zliczanie występujących wartości.

Witaj

HashMap przechowuje w sobie dane na zasadzie "klucz" - "wartość". W Twoim przypadku kluczem będzie słowo a wartością ilość jego wystąpień. W pętli możesz zrobić np. coś takiego:

String singleWord = items[i];
Integer licznik =(Integer) map.get(singleWord);
if(licznik == null){
licznik = new Integer(0);
}
licznik ++;
map.put(singleWord,licznik);

Wyświetlić możesz na console np. System.out.print(map);
Lub po kolei wybrać elementy z mapy i je wyświetlać

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

No więc tak... Żeby było wszystko zgodnie z prawidłami sztuki (i z kompilatorem javac ;-)) to HashMap powinna być zdefiniowana razem z typami, które będzie zawierać, czyli tak:


Map <String,Integer> map = new HashMap <String,Integer> ();


Następnie trzeba wpisać elementy tablicy do mapy:


Integer num;
for ( String item : items ) {
num = map.get(item);
if ( num == null ) num = 0;
map.put( item, ++num );
}



Nie jestem pewien, czy ten "++num" przejdzie, bo num jest obiektem klasy Integer a nie zmienną typu int, ale w Javie od jakiegoś czasu jest tzw "autoboxing", więc powinno pójść.Grzegorz Hołdys edytował(a) ten post dnia 22.12.08 o godzinie 20:34
Michał Rojek

Michał Rojek Programista J2EE,
CoreTeam

Temat: HashMap i zliczanie występujących wartości.

Nie jestem pewien, czy ten "++num" przejdzie, bo num jest obiektem klasy Integer a nie zmienną typu int, ale w Javie od jakiegoś czasu jest tzw "autoboxing"

"++num" przejdzie jeżeli będzie używana przynajmniej java 1.5:D

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Też mi się tak wydaje. Zresztą jeśli nie jest używana Java 1.5+ to "generics" też nie przejdzie :-P

Pozdrawiam
Michał Rojek

Michał Rojek Programista J2EE,
CoreTeam

Temat: HashMap i zliczanie występujących wartości.

Racja
Dorzucę od siebie jeszcze for each.

PozdrawiamMichał Rojek edytował(a) ten post dnia 22.12.08 o godzinie 20:37

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Wniosek z tego taki, że między Javą 1.5 a poprzednimi wersjami są tak duże różnice, że to już prawie inny język :-)

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Regexy chyba też są od niedawna w Javie :-P
Olga Grabek

Olga Grabek Senior Software
Engineer

Temat: HashMap i zliczanie występujących wartości.

Super, wpadłam na to by to napisy były kluczami, ale jakoś nie mogłam tego spiąć razem. Dzięki :)
Michał Rojek

Michał Rojek Programista J2EE,
CoreTeam

Temat: HashMap i zliczanie występujących wartości.

"Prawie" robi dużą różnicę
Ale fakt faktem pomiędzy 1.4 a 1.5 jest wiele smaczków.
Michał Rojek

Michał Rojek Programista J2EE,
CoreTeam

Temat: HashMap i zliczanie występujących wartości.

Grzegorz Hołdys:
Regexy chyba też są od niedawna w Javie :-P

Od wersji 1.4 :D
Zacheusz Siedlecki

Zacheusz Siedlecki Senior Java
Architect, Working
Manager

Temat: HashMap i zliczanie występujących wartości.

Wpisałem w edytorze goldenline, więc może się nie kompilować ;p

// pobranie napisów wprowadzonych do wiersza poleceń
String dane = JOptionPane.showInputDialog("Podaj napisy oddzielone przecinkami");
final String REGEX = "\\s*,\\s*";
Pattern p = Pattern.compile(REGEX);
String[] items = p.split(dane);
HashMap<String, Integer> map = new HashMap <String, Integer> ();
for (String token : items) {
Integer counter = map.get(token);
if (counter == null) {
counter = 0;
}
map.put(token, ++counter);
}

EDIT: oo widze, że mnie uprzedziliście :D
U mnie ta różnica, że regex jeszcze omija spacje przed i po przecinkach
EDIT 2: zmieniłem ? na * - będzie wolniej działać, ale weźmie pod uwagę więcej spacji. Jeśli ciągi wejściowe będą długie i to będzie zamulać to można podać limit branych pod uwagę spacji w {}Zacheusz Siedlecki edytował(a) ten post dnia 22.12.08 o godzinie 20:54

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Osz Ty spryciarzu jeden! :-PGrzegorz Hołdys edytował(a) ten post dnia 22.12.08 o godzinie 20:56

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Jakby się uprzeć to pewnie można by postawić tezę, że kompilowanie regexów do tak prostych zadań jest lekką przesadą i wpisać "\\s*,\\s*" bezpośrednio do wywołania metody split.
Zacheusz Siedlecki

Zacheusz Siedlecki Senior Java
Architect, Working
Manager

Temat: HashMap i zliczanie występujących wartości.

W przypadku wywołania w pętli ma to jak najbardziej cel. Zwiększa prędkość. Wewnątrz metody split w String jest
 Pattern.compile(wyrazenie).split(

W tym przypdaku rzeczywiście nie było to konieczne.Zacheusz Siedlecki edytował(a) ten post dnia 22.12.08 o godzinie 21:02

konto usunięte

Temat: HashMap i zliczanie występujących wartości.

Można też zastosować http://code.google.com/p/google-collections/
A dokładniej klasę MultiSet, która dla działa jak normalny Set, tylko z różnicą, że przy dodawaniu ponownie do zbioru tego samego elementu jest zwiększany licznik wystąpień.

String[] words = ...
Multiset multiset = Multisets.newHashMultiset();
for(String word : words) {
multiset.add(word);
}

for(String word : multiset.elementSet()) {
System.out(word + " " + multiset.count(word);
}
Damian Ł. edytował(a) ten post dnia 25.12.08 o godzinie 18:03



Wyślij zaproszenie do