Подтвердить что ты не робот

Поток против Итератора в entrySet Карты

Насколько я понимаю, следующий код должен вывести true, так как Stream и Iterator указывают на первый элемент.

Однако, когда я запускаю следующий код, он печатает false:

final HashMap<String, String> map = new HashMap<>();
map.put("A", "B");
final Set<Map.Entry<String, String>> set = Collections.unmodifiableMap(map).entrySet();
Map.Entry<String, String> entry1 = set.iterator().next();
Map.Entry<String, String> entry2 = set.stream().findFirst().get();
System.out.println(entry1 == entry2);

В чем причина разного поведения?

4b9b3361

Ответ 1

Обе записи ссылаются на одну и ту же логическую запись вашей Карты (чей ключ "A", а значение "B" ). Однако они не являются тем же самым экземпляром.

Если вы выровняете достаточно глубоко в реализации Collections.unmodifiableMap(map), вы увидите, что итерация по entrySet на карте, возвращаемой Collections.unmodifiableMap(map), возвращает новый Map.Entry, который обертывает исходную модифицируемую запись:

public Map.Entry<K,V> next() {
  return new UnmodifiableEntry<>(i.next());
}

Я предполагаю, что экземпляр экземпляра Map.Entry создается также при вызове set.stream().findFirst().get(), поэтому два метода возвращают разные экземпляры.

Даже если вы вызовете тот же метод дважды, вы получите разностные экземпляры, т.е. следующий код также напечатает false:

Map.Entry<String, String> entry1 = set.iterator().next();
Map.Entry<String, String> entry2 = set.iterator().next();
System.out.println(entry1 == entry2);

С другой стороны, если вы получите запись непосредственно из оригинала HashMap, вы получите true:

Map.Entry<String, String> entry1 = map.entrySet ().iterator().next();
Map.Entry<String, String> entry2 = map.entrySet ().stream().findFirst().get();
System.out.println (entry1==entry2);

Если в этом случае запись не завершается новым экземпляром, так что оба entrySet ().iterator().next() и entrySet ().stream().findFirst().get() возвращают один и тот же экземпляр.

Ответ 2

Дело в том, что

Map.Entry<String, String> entry1 = set.iterator().next();
Map.Entry<String, String> entry2 = set.stream().findFirst().get();

Вы не сравниваете значения , которые вы положили на карту. Но Ввод объектов!

Другими словами: похоже, что ваш код создает объекты new Entry, используя ваш код. Это полностью зависит от внутренней реализации этой немодифицируемой Карты/Установить, что нужно вернуть, когда ее запрашивают итератор или поток... и поскольку Эран был немного быстрее в поиске: причина в том, что новый Объекты ввода создаются при итерации.

Итак, при использовании equals() вместо ==... вы получите ожидаемый результат.

Ответ 3

Оба параметра entry1 и entry2 имеют одинаковое значение, но они не указывают один и тот же объект, потому что каждый раз, когда вы получаете объект Map.Entry, он создает новый.
Посмотрите на приведенный ниже код:

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Test1 {

    public static void main(String[] args) {
        final HashMap<String, String> map = new HashMap<>();
        map.put("A", "B");
        final Set<Map.Entry<String, String>> set = Collections.unmodifiableMap(map).entrySet();
        Map.Entry<String, String> entry1 = set.iterator().next();
        Map.Entry<String, String> entry2 = set.stream().findFirst().get();
        System.out.println("entry1 : " + System.identityHashCode(entry1));
        System.out.println("entry2 : " + System.identityHashCode(entry2));
        for (int i = 0; i < 5; i++) {
            System.out.println("directly for set " + i + " : " + System.identityHashCode(set.stream().findFirst().get()));
        }
    }
}

Вывод:

entry1 : 1283928880
entry2 : 295530567
directly for set 0 : 2003749087
directly for set 1 : 1324119927
directly for set 2 : 990368553
directly for set 3 : 1096979270
directly for set 4 : 1078694789

System.identityHashCode() выдаст хэш-код.