前面通过观察源码分析了Map和Set的相似之处,当把Map中的key-value对当成单独的集合元素来等待时,Map和Set也就统一起来了。接下来依然把Map的key-value对分开来对待,从另外一个角度来看,其实我们也可以把Map和List统一起来。
Map的values()方法:
Map集合是一个关联数值,它包含两组值: 一组是所有key组成的集合,key值不允许重复,而且Map不会保存key加入的顺序。因此这些key可以组成一个Set集合。另外一组是value组成的集合,因为Map集合的value完全可以重复,所以这些value可以组成一个List集合。
我们知道Map集合的keySet()方法可以返回一个Set集合。但Map的values()方法并未返回一个List集合:
HashMap<String , Double> scores = new HashMap<String , Double>(); scores.put("java" , 89.0); scores.put("Android" , 83.0); scores.put("Spring" , 80.0); System.out.println(scores.values()); System.out.println(scores.values().getClass()); TreeMap<String , Double> health = new TreeMap<String , Double>(); health.put("Linux" , 173.0); health.put("Git" , 71.2); System.out.println(health.values()); System.out.println(health.values().getClass());输出:
[ 89.0,83.0,80.0 ] class java.util.HashMap$Values [ 71.2,173.0 ] class java.utill.TreeMap$Values可以看出,HashMap和TreeMap两个集合的values()方法返回值确实是包含Map中所有value的集合。但他们不是正在的List对象,而分别是HashMap$Value对象和TreeMap$Value对象。
观看values()方法源码:
/** * 返回此映射所包含的值的 Collection 视图。 * 该 collection 受映射的支持,所以对映射的更改将反映在该 collection 中, * 反之亦然。如果在对 collection 进行迭代的同时修改了映射(通过迭代器自己的 remove 操作除外), * 则迭代结果是不确定的。该 collection 支持元素的移除, * 通过 Iterator.remove、Collection.remove、removeAll、retainAll 和 clear 操作 * 可从该映射中移除相应的映射关系。它不支持 add 或 addAll 操作。 */ public Collection<V> values() { Collection<V> vs = values; return (vs != null ? vs : (values = new Values())); }当程序第一次调用这两个Map对象的values()方法时,它们会新建一个Values()对象,并将Values()对象赋值给values实例变量。当程序下次调用values()方法时,将直接以values实例变量作为返回值。
观察HashMap的Values()内部类的源码:
// 内部类Values private final class Values extends AbstractCollection<V> { public Iterator<V> iterator() { //返回newValueIterator()方法的返回值 return newValueIterator(); } public int size() { //返回外部类size实例变量的返回值 return size; } public boolean contains(Object o) { //返回外部类实例的 containsValue(o)的返回值作为本方法的返回值 return containsValue(o); } public void clear() { //调用其外部类实例的clear()方法 HashMap.this.clear(); } }注意Values集合类,它虽然继承了AbstractCollection抽象类,但它并非是一个真正的Collection集合。因为它并未实现add(Object e)方法,而且该抽象类也没有实现add(Object e)方法,也就是说,这个Values集合对象并没有真正盛称任何java对象。
Values内部类的inerator()方法返回一个ValueIterator()类。
public final Iterator<V> iterator() { return new ValueIterator(); }ValueIterator类的实现非常简单,它是通过调用HashMap的nextNode()方法来实现的。
final class ValueIterator extends HashIterator implements Iterator<V> { public final V next() { return nextNode().value; } }