-2
public class KeySetImmutable {
    public static void main(String[] args) {
        Map<String, String> hashMap = new HashMap<>();
        
        hashMap.put("Key1", "String1");
        hashMap.put("Key2", "String2");
        hashMap.put("Key3", "String3");
        hashMap.put("Key4", "String4");
        
        Set<String> keySet = hashMap.keySet();
        
        keySet.add("Key4");
        
        System.out.println(hashMap.keySet());
        System.out.println(keySet);
    }
}

在上面的代码中keySet.add("Key4")抛出java.lang.UnsupportedOperationException. 这是否意味着这个特定的 Set 实例是一个防止添加键的特殊实现?底层实现如何实现这一点?

keySet.remove("Key3");工作正常并从 中删除元素HashMap

4

1 回答 1

3

keySet()返回覆盖但继承's的特定Set实现,后者继承's ,后者抛出.remove()AbstractSetadd()AbstractCollectionadd()UnsupportedOperationException

public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

final class KeySet extends AbstractSet<K> {
    ...
    public final boolean remove(Object key) {
        return removeNode(hash(key), key, null, false, true) != null;
    }
    ...
}

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> {
   ...
}

public abstract class AbstractCollection<E> implements Collection<E> {
    ...
    /**
     * {@inheritDoc}
     *
     * @implSpec
     * This implementation always throws an
     * {@code UnsupportedOperationException}.
     *
     * @throws UnsupportedOperationException {@inheritDoc}
     * @throws ClassCastException            {@inheritDoc}
     * @throws NullPointerException          {@inheritDoc}
     * @throws IllegalArgumentException      {@inheritDoc}
     * @throws IllegalStateException         {@inheritDoc}
     */
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
    ...
}

请注意,这些只是特定 JDK 版本的实现细节。

重要的是 Javadoc 的keySet()状态:

返回此映射中包含的键的集合视图。集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射(通过迭代器自己的删除操作除外),则迭代的结果是不确定的。该集合支持元素移除,即通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear 操作从映射中移除相应的映射它不支持 add 或 addAll 操作

于 2020-07-20T08:35:10.120 回答