recorrer ordenado example entre diferencia java hashmap iterator java-stream entryset

java - ordenado - Corriente contra iterador en entrySet de un mapa



recorrer un linkedhashmap java (3)

Ambas entradas se refieren a la misma entrada lógica de su Mapa (cuya clave es "A" y el valor es "B"). Sin embargo, no son la misma instancia.

Si profundiza lo suficiente en la implementación de Collections.unmodifiableMap(map) verá que la iteración sobre el entrySet del mapa devuelto por Collections.unmodifiableMap(map) devuelve un nuevo Map.Entry que envuelve la entrada modificable original:

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

Supongo que también se crea una nueva instancia de Map.Entry cuando llama a set.stream().findFirst().get() , por lo que los dos métodos devuelven instancias diferentes.

Incluso si llama al mismo método dos veces, obtendrá instancias de diferencia, es decir, el siguiente código también se imprimirá como false :

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

Por otro lado, si obtiene la entrada directamente del HashMap original, obtendrá la 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);

En este caso, la entrada no se entrySet ().iterator().next() una nueva instancia, por lo que tanto entrySet ().iterator().next() entrySet ().stream().findFirst().get() como entrySet ().stream().findFirst().get() devuelven la misma instancia.

A mi entender, el siguiente código debe imprimirse true , ya que tanto Stream como Iterator están apuntando al primer elemento.

Sin embargo, cuando ejecuto el siguiente código se imprime 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);

¿Cuál es la razón de la diferente conducta?


La cosa es:

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

No estás comparando los valores que pusiste en el mapa. Pero los objetos de entrada !

En otras palabras: parece que su código está creando nuevos objetos de entrada utilizando su código. Depende completamente de la implementación interna de ese Map / Set no modificable que devolver cuando se solicita un iterador o un flujo ... y como Eran fue un poco más rápido de buscar: la razón es que se crean nuevos objetos de Entry cuando iterando

Entonces, cuando se usa equals() lugar de == ... se obtiene el resultado esperado.


No tanto entry1 como entry2 tienen el mismo valor, pero no apuntan al mismo objeto porque cada vez que obtiene el objeto Map.Entry , crea uno nuevo.
Mira el siguiente código:

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())); } } }

La salida es:

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() dará código hash.