乐趣区

关于java:HashMapvaluesaddAll异常

问题:在应用一个 Collection.addAll() 办法时报告 UnsupportedOperationException。追溯起因发现该 collection 是来自于 hashMap.values()。

剖析起因:通过查看源代码,发现 hashMap.values() 实现如下:

//HashMap.java
public Collection<V> values() {

    Collection<V> vs = values;
    return (vs != null ? vs : (values = new Values()));
}

  private final class Values extends AbstractCollection<V> {public Iterator<V> iterator() {return newValueIterator();
    }
    public int size() {return size;}
    public boolean contains(Object o) {return containsValue(o);
    }
    public void clear() {HashMap.this.clear();
    }
}

// 其中 values 的定义如下:AbstractMap.java
  transient volatile Collection<V> values = null;
   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;
}

从下面代码看到,hashMap.values() 先看 values 是否为空:

如果不为空,则间接返回 values。values 是在在 AbstractMap 中定义的,初始化时 new 了一个 AbstractCollection,并实现了若干办法,然而并没有实现 all() 和 addAll() 办法。

如果为空,则 new 一个外部实现类 Values。Values 同样没有实现 AbstractCollection 的没有实现 all() 和 addAll() 办法。

再来看一下 AbstractCollection 的 add() 和 addAll() 办法:

//AbstractCollection.java
public boolean add(E e) {

    throw new UnsupportedOperationException();}

public boolean addAll(Collection<? extends E> c) {

    boolean modified = false;
    for (E e : c)
        if (add(e))
            modified = true;
    return modified;
}

能够看到,add 办法的实现是间接抛出 UnsupportedOperationException,addAll 办法调用 add 办法,也间接抛出异样,同样的,HashMap.values() 调用 add() 和 addAll() 也会抛出异样。

论断:通过以上剖析,明确了 HashMap.values() 调用 add() 和 addAll() 抛出异样的起因。也通知咱们在理论应用中,要留神防止间接应用 HashMap.values().add() 和 HashMap.values().addAll()。
另外:HashMap.vKeySet(),HashMap.entrySet() 调用 add() 和 addAll() 办法也是如此。

退出移动版