Должен ли я использовать итератор, чтобы сделать цикл над HashMap? - PullRequest
3 голосов
/ 08 декабря 2010

У меня есть HashMap<String,String> (называемый p2p), и я хочу сделать цикл над его элементами. Я нашел следующий простой способ сделать это:

for (String key : p2p.keySet()) {
   value = p2p.get(key);
}

Однако позже я узнал, что люди используют iterator(). Например:

Iterator it = p2p.keySet().iterator();
while(it.hasNext()) {
    key = it.next();
    value = p2p.get(key);
}

Для меня первый способ выглядит проще. Итак, мой вопрос: почему люди используют второй способ? Есть ли у него какие-то объективные преимущества или это просто вопрос вкуса и субъективности простоты?

Ответы [ 7 ]

8 голосов
/ 08 декабря 2010

Они одинаковы - улучшено для цикла использует итератор для получения элементов (если вы не выполняете итерацию по массиву, в этом случае он использует длину и доступ к массиву под капотом.)

Лично я бы не стал выполнять итерацию подобным образом - я бы провел итерацию по парам ключ / значение:

for (Map.Entry<String, String> entry : p2p.entrySet()) {
    String key = entry.getKey();
    String value = entry.getValue();
}

Таким образом, вам никогда не нужно делать какие-либо реальные поиски.

2 голосов
/ 08 декабря 2010

Второй (более старый) способ необходим, если вы хотите удалить элементы во время итераций, например, используйте Iterator.remove (). Вы не можете удалить элементы из коллекции во время итерации, используя collection.remove () - это создает исключение ConcurrentModificationException.

Приведенное выше описание в основном относится к коллекциям (списки, наборы).

1 голос
/ 08 декабря 2010

Перейти на EntrySet, если вы хотите, чтобы и ключ, и элемент:

Вот базовый пример:

HashMap<String, Person> hm = new HashMap<String, Person>();

hm.put("A", new Person("p1"));
hm.put("B", new Person("p2"));
hm.put("C", new Person("p3"));
hm.put("D", new Person("p4"));
hm.put("E", new Person("p5"));

Set<Map.Entry<String, Person>> set = hm.entrySet();

for (Map.Entry<String, Person> me : set) {
  System.out.println("Key :"+me.getKey() +" Name : "+ me.getValue().getName()+"Age :"+me.getValue().getAge());

}
0 голосов
/ 08 декабря 2010

Если вам нужно перебрать значения, выполните:

for(String value: map.values(){
   ...
}

Если вам нужно перебрать пары ключ-значение, выполните:

for(Map.Entry<String, String> entry: map.entrySet()){
   ... entry.getKey(); 
   ... entry.getValue();
}

Помните, что вы ДОЛЖНЫ использовать явный итератор (вместо foreach), когда хотите удалить что-то из коллекции во время итерации.

0 голосов
/ 08 декабря 2010

Существует две причины использования второго метода:

  • Незнание о существовании расширенного цикла for.
  • Он более мощный - с Iterator вы можете проверить, есть ли больше элементов с hasNext(), и вы можете удалить элементы во время итерации списка.
0 голосов
/ 08 декабря 2010

Первый способ не всегда возможен на языке Java.Это в основном ярлык для второго пути.

0 голосов
/ 08 декабря 2010

Я могу подумать о нескольких причинах, по которым можно использовать второй (явный итератор) способ:

  1. «Цикл foreach» был введен только в Java 5, поэтому код, написанный для более старых JVM, не сможет этого сделать.
  2. Цикл foreach работает только с простыми (хотя и общими) идиомами, когда вы имеете дело только с одним элементом за раз. В частности, он не позволяет запрашивать метод итератора hasNext(), который часто бывает полезен, или делать что-то, где вы берете пары значений и упаковываете их в карту и т. Д.

Тем не менее, для ваших целей вы правы, явный итератор не дает никаких преимуществ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...