Map<Integer, String> map = new TreeMap<>();
map.put(1, "String1");
map.put(2, "String2");
map.put(3, "String3");
我想转换map
的值来设置。我知道我可以轻松做到
Set<String> set = new HashSet<>(map.values());
考虑这个问题时,我很好奇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));
输出令人惊讶地是
Set:false
List:false
Queue:false
SortedSet:false
This是所有文档说明的内容。
此地图中包含的值的集合视图
然后我查看了反编译的类文件。
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;
}
为什么Java返回抽象实现而不是可以立即与用例兼容的List
/ Set
/ Queue
?
答案 0 :(得分:5)
我不知道您使用的是哪个Java版本,但是我看不到values()
返回的抽象类实例。它返回TreeMap.Values
的实例,该实例是扩展AbstractCollection
的类。
关于为什么它不返回Set
的原因-这仅是由于值的集合可能包含重复项,而Set
不允许重复。
List
也不理想,因为这暗示着值是有序的,这对于所有Map
实现(例如HashMap
)都不正确。
顺便说一句,您不必打印map.values() instanceof Set
之类的东西,而只需打印map.value().getClass().getName()
就可以看到实际的实现类。
答案 1 :(得分:3)
仅从实现上看有一个原因:contains
和iterator
都查看映射的当前内容,而不是调用values()
时的映射内容。 / p>
如果您呼叫values()
,然后更改地图中的某些内容,则更改将反映在最初从Collection
返回的values()
中。
Map<String, String> map = new HashMap<String, String>();
map.put("some", "thing");
Collection<String> values = map.values();
System.out.println(values.size()); // 1
map.put("foo", "bar");
System.out.println(values.size()); // 2
答案 2 :(得分:1)
哈希集在内部使用HashMap,因此在场景中不会出现太多的值副本。
您可以查看相关链接以获取更多信息。 Reference Link。
抽象收集的地方,下面是从Java Doc获取的一些相关信息:
1]此类提供Collection的骨架实现 接口,以最小化实现此接口所需的工作。
2]要实现不可修改的集合,程序员只需要
扩展此类并为<tt>iterator</tt>
提供实现
<tt>size</tt>
个方法。 (<tt>iterator</tt>
返回的迭代器
方法必须实现<tt>hasNext</tt>
和<tt>next</tt>
。
3]要实现可修改的集合,程序员必须另外
覆盖此class's <tt>add</tt>
方法(否则将抛出
UnsupportedOperationException
),然后由
迭代器方法必须另外实现其remove
方法。
希望这会有所帮助。