Skip to content

Java

介绍

  • 不可变集合就是不可以被修改的集合
  • 常见场景, 例如: 不想让别人修改集合中的内容, 比如斗地主的牌, 电脑硬件信息
  • 特点: 只可以查询, 但不可以修改

书写格式

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

类型集合
static <E> List<E> of(E... element)List
static <E> Set<E> of(E... element)Set
static <K, V> Map<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)Map

创建不可变集合List

Demo1.java
java
import java.util.List;
//创建不可变集合List
public class Demo1 {
    public static void main(String[] args) {
        List<String> list = List.of("1", "2", "3");
        //对不可变集合使用除查询以外的方法, 会报错
        list.add("6");

        for (String s : list) {
            System.out.println(s);
        }
    }
}

危险

对不可变集合使用除查询以外的方法, 会报错java.lang.UnsupportedOperationException


创建不可变集合Set

Demo1.java
java
import java.util.Set;

public class Demo1 {
    public static void main(String[] args) {
        Set<String> set = Set.of("a", "b", "c");
//        报错java.lang.UnsupportedOperationException
        set.add("t");
        //a b c
        set.forEach(s -> System.out.println(s));

        //使用注意点: 当创建一个不可变的Set集合时, 里面的参数需要保证唯一性
        Set<String> set1 = Set.of("a", "a", "b", "c");
        //报错java.lang.IllegalArgumentException: duplicate element: a
        System.out.println(set1);
    }
}

危险

  1. 对不可变集合使用除查询以外的方法, 会报错java.lang.UnsupportedOperationException
  2. 当创建一个不可变的Set集合时, 里面的参数需要保证唯一性, 不然会报错java.lang.IllegalArgumentException

创建不可变集合Map

Demo1.java
java
import java.util.Map;

public class Demo2 {
    public static void main(String[] args) {
        //此方法最多只支持10对键值对
        Map<String, Integer> map = Map.of("A", 1, "B", 2);
        System.out.println(map);//{A=1, B=2}
//        map.put("C", 3);//java.lang.UnsupportedOperationException
    }
}

提示

此方法最多只支持10对键值对, 如何理解呢? 如果希望一个方法可以接收多个参数, 那么第一时间想到的就是可变参数, 可使用可变参数就无法保证类型信息正确, 即无法分清是键还是值, 它们都是统一的类型.

java
public static void method(int... e) {
        /* ... */
}
//无法分清是键还是值, 它们都是统一的类型
method(1, 2, 4, 3, 4, 5);

ofEntries的使用

如果需要创建超过10对键值对, 可以使用Map.ofEntries()

java
import java.util.HashMap;
import java.util.Map;

public class Demo3 {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("张三", "北京");
        map.put("李四", "上海");
        map.put("王五", "武汉");
        //1. 获取Entry对象集合
        Set<Map.Entry<String, String>> entries = map.entrySet();
        //使用空参默认返回Object[]类型
//        Object[] arr1 = entries.toArray();
        //创建长度为0的Entry数组
        Map.Entry[] arr = new Map.Entry[0];
        //toArray方法在底层会比较集合的长度和数组的长度两者的大小
        //1. 如果集合长度 > 数组长度 ==> 数据在数据中放不下, 此时会根据实际数据的个数, 重新创建数组
        //2. 如果集合长度 <= 数组长度 ==> 数据放的下, 此时不会创建新的数组, 而是直接用
        Map.Entry[] arr1 = entries.toArray(arr);
        //相当于: Map.Entry[] arr1 = entries.toArray(new Map.Entry[0]);
        //参数接收的是Entry[], 因为可变参数实际上就是一个数组
        Map map1 = Map.ofEntries(arr1);
        System.out.println(map1);//{王五=武汉, 张三=北京, 李四=上海}
    }
}

toArray()

  1. 如果集合长度 > 数组长度 ==> 数据在数据中放不下, 此时会根据实际数据的个数, 重新创建数组
  2. 如果集合长度 <= 数组长度 ==> 数据放的下, 此时不会创建新的数组, 而是直接用

前面所写创建不可变集合Map的方法太过繁琐, 以下是简略写法:

java
Map<Object, Object> map3 = Map.ofEntries(map.entrySet().toArray(new Map.Entry[0]));

copyOf的使用

即便使用ofEntries创建对象, 但还是太繁琐了. 在JDk10的时候, 提供了copyOf方法, 此方法只需传入一个Map集合便可以返回不可变Map.

java
HashMap<String, String> map = new HashMap<>();
map.put("张三", "北京");
map.put("李四", "上海");
map.put("王五", "武汉");
//创建不可变集合Map, 但
Map<String, String> map4 = Map.copyOf(map);

Released under the MIT License.