Why abstract implementation is returned by Map.values()?

Arun S R :
Map<Integer, String> map = new TreeMap<>();
map.put(1, "String1");
map.put(2, "String2");
map.put(3, "String3");

I wanted to convert the map's values to set. I know I could easily do

Set<String> set = new HashSet<>(map.values());

While thinking about this, I was curious what is map.values() by itself anyway? So I tried this

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

And the output surprisingly was

Set:false
List:false
Queue:false
SortedSet:false

This is all the documentation says.

a collection view of the values contained in this map

I then looked at the decompiled class file.

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

Why does java return an abstract implementation instead of List/Set/Queue which could be immediately compatible with use cases?

Eran :

I don't know which Java version you are using, but I don't see an abstract class instance returned by values(). It returns an instance of TreeMap.Values, which is a class that extends AbstractCollection.

As to why it doesn't return a Set - that's simply due to the fact that the collection of values may contain duplicates, which a Set doesn't allow.

A List is also not ideal, since it would imply the values are ordered, which is not true for all Map implementations (such as HashMap).

BTW, instead of printing things like map.values() instanceof Set, you could have simply printed map.value().getClass().getName() to see the actual implementation class.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=122442&siteId=1