коллекции Java - keyset () против entrySet () на карте - PullRequest
32 голосов
/ 22 января 2012

Я поместил элементы массива строк - это карта, где элементы массива строк - это ключ, а частота слова - это значение, например ::100100

String[] args = {"if","it","is","to","be","it","is","up","me","to","delegate"};

тогда на карте будут записи типа [ if:1, it:2 .... ]

Set<String> keys = m.keySet();
System.out.println("keyset of the map : "+keys);

печатает все ключи: "if","it","is","to","be","it","is","up","me","to","delegate"

Set<Map.Entry<String, Integer>> entrySet = m.entrySet();
Iterator<Map.Entry<String, Integer>> i = entrySet.iterator();
while(i.hasNext()){
    Map.Entry<String, Integer> element = i.next();
    System.out.println("Key: "+element.getKey()+" ,value: "+element.getValue());
}

печатает все пары значений ключа:

При вводе набора печатает все значения:

Key: if ,value: 1
Key: it ,value: 2
Key: is ,value: 2
Key: to ,value: 2
Key: be ,value: 1
Key: up ,value: 1
Key: me ,value: 1
Key: delegate ,value: 1

Но блок кода ниже должен выводить точно такой же вывод, как и выше, но это не так:

Iterator<String> itr2 = keys.iterator();
while(itr2.hasNext()){
    //System.out.println(itr1.next()+" ");
    //System.out.println(m.get(itr1.next())+" ");
    System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next()));
}

Он печатает:

Key: if ,value: 2
Key: is ,value: 2
Key: be ,value: 1
Key: me ,value: 1

Но если мы раскомментируем строку 1 в цикле while, т.е.

System.out.println(itr1.next()+" ");

и прокомментируйте строку

System.out.println("Key: "+itr2.next()+" ,value: "+m.get(itr2.next()));

Тогда мы получим все ключи: {"if","it","is","to","be","it","is","up","me","to","delegate"};

Если мы используем m.get() с itr2.next(), то у итератора мало ключей!

Ответы [ 5 ]

48 голосов
/ 22 января 2012

Каждый вызов Iterator.next() перемещает итератор к следующему элементу. Если вы хотите использовать текущий элемент в более чем одном выражении или выражении, вы должны сохранить его в локальной переменной. Или даже лучше, почему бы вам просто не использовать цикл for-each?

for (String key : map.keySet()) {
    System.out.println(key + ":" + map.get(key));
}

Более того, цикл по entrySet выполняется быстрее, потому что вы не запрашиваете карту дважды для каждого ключа. Также реализации Map.Entry обычно реализуют метод toString(), поэтому вам не нужно печатать пару ключ-значение вручную.

for (Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry);
}
3 голосов
/ 22 января 2012

Каждый раз, когда вы вызываете itr2.next (), вы получаете различное значение. Не то же значение. Вы должны вызывать это только один раз в цикле.

Iterator<String> itr2 = keys.iterator();
    while(itr2.hasNext()){
        String v = itr2.next();
        System.out.println("Key: "+v+" ,value: "+m.get(v));
    }
2 голосов
/ 11 марта 2014

Обход по большой карте entrySet() намного лучше, чем keySet().Посмотрите этот учебник, как они оптимизируют обход большого объекта с помощью entrySet() и как это помогает для настройки производительности.

1 голос
/ 22 января 2012

Iterator движется только вперед, если он прочитал его один раз, все готово.Ваш

m.get(itr2.next());

читает следующее значение itr2.next();, поэтому вам не хватает нескольких (на самом деле не мало, все остальные) клавиш.

0 голосов
/ 07 декабря 2016

Чтобы упростить задачу, обратите внимание, что каждый раз, когда вы делаете itr2.next(), указатель перемещается к следующему элементу, то есть здесь, если вы внимательно обратите внимание, то вывод будет совершенно в соответствии с написанной вами логикой.
Это может помочь вам лучше понять:

1-я итерация цикла While (указатель находится перед 1-м элементом):
Ключ: если, значение: 2 {itr2.next()=if; m.get(itr2.next()=it)=>2}

2-я итерация цикла While (указатель перед 3-м элементом):
Ключ: есть, значение: 2 {itr2.next()=is; m.get(itr2.next()=to)=>2}

3-я итерация цикла While (указатель перед 5-м элементом):
Ключ: be, значение: 1 {itr2.next()="be"; m.get(itr2.next()="up")=>"1"}

Четвёртая итерация цикла While (указатель перед седьмым элементом):
Ключ: я, значение: 1 {itr2.next()="me"; m.get(itr2.next()="delegate")=>"1"}

Ключ: если, значение: 1
Ключ: это, значение: 2
Ключ: есть, значение: 2
Ключ: до, значение: 2
Ключ: be, значение: 1
Ключ: вверх, значение: 1
Ключ: я, значение: 1
Ключ: делегат, значение: 1

Он печатает:

Ключ: если, значение: 2
Ключ: есть, значение: 2
Ключ: be, значение: 1
Ключ: я, значение: 1

...