为什么Map.values()返回抽象实现?

Aru*_*pal 3 java collections

Map<Integer, String> map = new TreeMap<>();
map.put(1, "String1");
map.put(2, "String2");
map.put(3, "String3");
Run Code Online (Sandbox Code Playgroud)

我想将map的值转换为set。我知道我可以轻松做到

Set<String> set = new HashSet<>(map.values());
Run Code Online (Sandbox Code Playgroud)

在考虑这一点时,我很好奇它到底是什么map.values()?所以我尝试了这个

System.out.println("Set:"+ (map.values() instanceof Set));      
System.out.println("List:"+ (map.values() instanceof List));    
System.out.println("Queue:"+ (map.values() instanceof Queue));
System.out.println("SortedSet:"+ (map.values() instanceof SortedSet));
Run Code Online (Sandbox Code Playgroud)

输出令人惊讶的是

Set:false
List:false
Queue:false
SortedSet:false
Run Code Online (Sandbox Code Playgroud)

就是所有文档所说的。

此地图中包含的值的集合视图

然后,我查看了反编译的类文件。

public Collection<V> values() {
    if (values == null) {
        values = new AbstractCollection<V>() {
            public Iterator<V> iterator() {
                return new Iterator<V>() {
                    private Iterator<Entry<K,V>> i = entrySet().iterator();

                    public boolean hasNext() {
                        return i.hasNext();
                    }

                    public V next() {
                        return i.next().getValue();
                    }

                    public void remove() {
                        i.remove();
                    }
                };
            }

            public int size() {
                return AbstractMap.this.size();
            }

            public boolean isEmpty() {
                return AbstractMap.this.isEmpty();
            }

            public void clear() {
                AbstractMap.this.clear();
            }

            public boolean contains(Object v) {
                return AbstractMap.this.containsValue(v);
            }
        };
    }
    return values;
}
Run Code Online (Sandbox Code Playgroud)

为什么Java返回一个抽象实现而不是List// Set/ Queue可以立即与用例兼容?

Era*_*ran 5

我不知道您使用的是哪个Java版本,但看不到所返回的抽象类实例values()。它返回的实例TreeMap.Values,它是扩展的类AbstractCollection

至于为什么它不返回Set-,这仅是由于值的集合可能包含重复项,而a Set不允许这样做。

A List也不理想,因为这将暗示值是有序的,这对于所有Map实现(例如HashMap)都不正确。

顺便说一句,您不必打印类似的内容map.values() instanceof Set,只需打印map.value().getClass().getName()即可查看实际的实现类。