Java 不可变集合

428 阅读2分钟

不可变集合

JDK9新特性

  • 不可变集合:不能别修改的集合
    • 长度不可修改
    • 内容不可修改

不可变集合的应用场景

  • 如果某个数据不能被修改,把它防御性地拷贝到不可变集合中是一个很好地时间
  • 当集合对象被不可信地库调用时,不可变形式是安全地
  • 简单理解:不想让别人修改集合中的内容

不可变集合的书写格式

再List、Set、Map接口中,都存在静态的of方法,可以获取一个不可变的集合

方法名称说明
static List of(E...elements)创建一个具有指定元素的List集合对象
static Set of(E...element)创建一个具有指定元素的Set集合对象
static<K, V> Map<K, V> of(E...elements)创建一个具有指定元素的Map集合对象
static<K, V> Map<K, V> ofEntris(Entry<? entends K, ? extends V>... entries)创建一个具有指定元素的Map集合对象
static<K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map)JDK10: 根据传入的map集合创建不可变集合

**注意:**这个集合不能添加,不能删除,不能修改

细节

  • 当我们要获取一个不可变的Set集合时,里面的参数一定要保证唯一性

  • 当我们要获取一个不可变的Map集合时,键不能重复

  • Map里面的of方法,参数是有上限的,最多只能有20个参数,即10个键值对,因为形参里面不能有多个可变参数

  • 如果我们传递多个键值对对象,数量大于10个,可以使用Map中的ofEntries方法

    • 方法原理:这个方法里面的形参是可变参数,而可变参数在底层就是一个数组,因此我们只需要获取entry数组再传入就行
//获取所有的键值对对象(Entry对象)
Set<Map.Enter<String, String>> entries = hm.entrySet();
//调用toArray方法将Set集合变成数组
Map.Entry[] arr1 = entries.toArray(new Map.Entry[0]);
//toArray方法再底层会比较集合的长度跟数组的长度两者的大小
//如果集合的长度 > 数组的长度:数据再数组中放不下,此时会根据实际数据的个数,重新创建数组
//如果集合的长度 <= 数组的长度:数据再数组中放得下,此时不会创建新的数组,而是直接用
//调用ofEntries方法创建不可变集合
Map<String, String> map = Map.ofEntries(arr1);
  • 链式法则简化
Map<String, String> map = Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0]))
  • copyOf方法底层原理
    • 首先判断传入的map集合本身是否为不可变集合
      • 如果是,强制类型转换后直接返回
      • 如果不是,调用ofEntries方法后强制类型转换并返回
static<K, V> Map<K, V> copyOf(Map<? extends K, ? extends V> map) {
    if (map instanceof ImmutableCollections.AbstractImmutableMap) {
        return (Map<K, V>)map;
    } else {
        return (Map<K, V>)Map.ofEntries(map.entrySet().toArray(new Entry[0]));
    }
}