简体   繁体   English

流对比 Map 的 entrySet 中的迭代器 - Java 8

[英]Stream Vs. Iterator in entrySet of a Map - Java 8

To my understanding, the following code should have print true , since both Stream and Iterator are pointing to the first element.根据我的理解,以下代码应该打印true ,因为StreamIterator都指向第一个元素。

However, when I ran the following code it is printing false :但是,当我运行以下代码时,它正在打印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);

What could be the reason for this different behavior?这种不同行为的原因可能是什么?

Both entries are referring to the same logical entry of your Map (whose key is "A" and value is "B").两个条目都指的是 Map 的相同逻辑条目(其键为“A”,值为“B”)。 However, they are not the same instance.但是,它们不是同一个实例。

If you dig deep enough in the implementation of Collections.unmodifiableMap(map) you'll see that iterating over the entrySet of the map returned by Collections.unmodifiableMap(map) returns a new Map.Entry which wraps the original modifiable entry:如果你在Collections.unmodifiableMap(map)的实现中挖掘得足够深,你会看到迭代Collections.unmodifiableMap(map)返回的地图的entrySet返回一个新的Map.Entry ,它包装了原始的可修改条目:

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

I'm assuming a new instance Map.Entry instance is also created when you call set.stream().findFirst().get() , so the two methods return different instances.我假设在调用set.stream().findFirst().get()时还会创建一个新实例Map.Entry实例,因此这两种方法返回不同的实例。

Even if you'll call the same method twice you'll get difference instances, ie the following code will also print false :即使您两次调用相同的方法,您也会得到不同的实例,即以下代码也会打印false

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

On the other hand, if you obtain the entry directly from the original HashMap , you will get true :另一方面,如果您直接从原始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);

If this case the entry is not wrapped by a new instance, so both entrySet ().iterator().next() and entrySet ().stream().findFirst().get() return the same instance.如果这种情况下条目没有被新实例包装,那么entrySet ().iterator().next()entrySet ().stream().findFirst().get()返回相同的实例。

The thing is:事情是:

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

You are not comparing the values you put into the map.您不是在比较放入地图中的 But Entry objects!但是Entry对象!

In other words: it looks like your code is creating new Entry objects using your code.换句话说:看起来您的代码正在使用您的代码创建新的Entry 对象。 It is completely up to the internal implementation of that unmodifiable Map/Set what to return when it is asked for an iterator or a stream ... and as Eran was a bit quicker to lookup: the reason is that new Entry objects are created when iterating .这完全取决于不可修改的 Map/Set 的内部实现,当它被要求提供迭代器或流时要返回什么......而且因为 Eran 查找起来要快一些:原因是新的Entry 对象是在以下情况下创建的迭代

So, when using equals() instead of == ... you get the expected output.因此,当使用equals()而不是== ...时,您会得到预期的输出。

No both entry1 and entry2 are has same value but they are not pointing the same object because the each time you get the Map.Entry object it create new one.没有entry1entry2具有相同的值,但它们没有指向同一个对象,因为每次获得Map.Entry对象时,它都会创建一个新对象。
Look at the below code :看看下面的代码:

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

The output is :输出是:

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() will give hash code. System.identityHashCode()将给出哈希码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM