Java 如何实现Hashmap的底层键集以使add方法失败? 公共类KeySetImmutable{ 公共静态void main(字符串[]args){ Map hashMap=新hashMap(); hashMap.put(“Key1”、“String1”); hashMap.put(“Key2”、“String2”); hashMap.put(“Key3”、“String3”); hashMap.put(“Key4”、“String4”); Set keySet=hashMap.keySet(); 键集添加(“键4”); System.out.println(hashMap.keySet()); System.out.println(键集); } }

Java 如何实现Hashmap的底层键集以使add方法失败? 公共类KeySetImmutable{ 公共静态void main(字符串[]args){ Map hashMap=新hashMap(); hashMap.put(“Key1”、“String1”); hashMap.put(“Key2”、“String2”); hashMap.put(“Key3”、“String3”); hashMap.put(“Key4”、“String4”); Set keySet=hashMap.keySet(); 键集添加(“键4”); System.out.println(hashMap.keySet()); System.out.println(键集); } },java,hashmap,jvm,keyset,Java,Hashmap,Jvm,Keyset,在上面的代码中,keySet.add(“Key4”)抛出java.lang.UnsupportedOperationException。这是否意味着Set的这个特定实例是防止添加键的特殊实现?底层实现是如何实现这一点的 鉴于keySet.remove(“Key3”)工作正常,并从HashMap中删除元素。keySet()返回一个特定的集实现,该实现覆盖remove(),但继承抽象集的添加(),它继承了抽象集合的添加(),它抛出不支持操作异常 public class KeySetImmutabl

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

鉴于
keySet.remove(“Key3”)
工作正常,并从
HashMap
中删除元素。

keySet()
返回一个特定的
实现,该实现覆盖
remove()
,但继承
抽象集
添加()
,它继承了
抽象集合
添加()
,它抛出
不支持操作异常

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);
    }
}
公共设置键集(){
设置ks=键集;
如果(ks==null){
ks=新键集();
键集=ks;
}
返回ks;
}
最终类键集扩展了抽象集{
...
公共最终布尔删除(对象键){
return removeNode(散列(key),key,null,false,true)!=null;
}
...
}
公共抽象类AbstractSet扩展了AbstractCollection实现集{
...
}
公共抽象类AbstractCollection实现集合{
...
/**
*{@inheritardoc}
*
*@implSpec
*这个实现总是抛出一个
*{@code UnsupportedOperationException}。
*
*@throws UnsupportedOperationException{@inheritardoc}
*@crows ClassCastException{@inheritDoc}
*@throws-NullPointerException{@inheritardoc}
*@inheritDoc}
*@throws-IllegalStateException{@inheritDoc}
*/
公共布尔加法(E){
抛出新的UnsupportedOperationException();
}
...
}
请注意,这些只是特定JDK版本的实现细节

重要的是
keySet()
的Javadoc说明了什么:

返回此映射中包含的键的集合视图。该集合由映射支持,因此对映射的更改将反映在集合中,反之亦然。如果在对集合进行迭代时修改映射(通过迭代器自己的移除操作除外),则迭代的结果是未定义的该集合支持元素移除,即通过迭代器.remove、set.remove、removeAll、retainal和clear操作从映射中移除相应的映射它不支持添加或添加所有操作

映射(
entrySet()
keySet()
values()
)提供的视图允许删除,但不允许添加。这几乎总是通过从
java.util
扩展
abstract
集合类来实现的,这些集合类不受defaultkeySet()的影响,不支持add或addAll操作。
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();
    }
    ...
}