给我半首歌的时间,给你说明白Immutable List
Immutable List,顾名思义,就是,啥,不明白 Immutable 是什么意思?一成不变的意思,所以 Immutable List 就是一个不可变的 List 类,这意味着该 List 声明后,它的内容就是固定的,不可增删改的。 如果对不可变类比较陌生的话,可以先点击下面的链接查看我之前写的另外一篇文章。 这次要说不明白immutable类,我就怎么地 如果尝试对 List 中的元素进行增加、删除或者更新,就会抛出 UnsupportedOperationException 异常。 另外,Immutable List 中的元素是非 null 的,如果使用 null 来创建 Immutable List,则会抛出 NullPointerException;如果尝试在 Immutable List 中添加 null 元素,则会抛出 UnsupportedOperationException。 那 Immutable List 有什么好处呢? 它是线程安全的; 它是高效的; 因为它是不可变的,就可以像 String 一样传递给第三方类库,不会发生任何安全问题。 那接下来,我们来看一下,如何创建 Immutable List。注意,源码是基于 JDK14 的。 01、借助原生 JDK Collections 类的 unmodifiableList() 方法可以创建一个类似于 Immutable List 的 UnmodifiableList 或者 UnmodifiableRandomAccessList,都是不可修改的。 publicstatic<T>List<T>unmodifiableList(List<?extendsT>list){return(listinstanceofRandomAccess?newCollections.UnmodifiableRandomAccessList<>(list):newCollections.UnmodifiableList<>(list));} 来看一下使用方法: List<String>list=newArrayList<>(Arrays.asList("沉默王二","沉默王三","沉默王四"));List<String>unmodifiableList=Collections.unmodifiableList(list); 我们尝试往 unmodifiableList 中添加元素“沉默王五”: unmodifiableList.add("沉默王五"); 运行后会抛出 UnsupportedOperationException 异常: Exceptioninthread"main"java.lang.UnsupportedOperationExceptionatjava.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1062)atcom.cmower.mkyong.immutablelist.ImmutableListDemo.main(ImmutableListDemo.java:16) 02、借助 Java 9 Java 9 的时候,List 类新增了一个 of() 静态工厂方法,可以用来创建不可变的 List。先来看一下源码: static<E>List<E>of(Ee1,Ee2,Ee3){returnnewImmutableCollections.ListN<>(e1,e2,e3);} of() 方法有很多变体,比如说: static<E>List<E>of(Ee1){returnnewImmutableCollections.List12<>(e1);}static<E>List<E>of(Ee1,Ee2){returnnewImmutableCollections.List12<>(e1,e2);}static<E>List<E>of(Ee1,Ee2,Ee3,Ee4){returnnewImmutableCollections.ListN<>(e1,e2,e3,e4);}static<E>List<E>of(Ee1,Ee2,Ee3,Ee4,Ee5){returnnewImmutableCollections.ListN<>(e1,e2,e3,e4,e5);}static<E>List<E>of(Ee1,Ee2,Ee3,Ee4,Ee5,Ee6,Ee7,Ee8,Ee9,Ee10){returnnewImmutableCollections.ListN<>(e1,e2,e3,e4,e5,e6,e7,e8,e9,e10);} 该方法的设计者也挺有意思的,of() 方法的参数,从 0 到 10 都有一个相同签名的重载方法。 甚至当参数是可变的时候,使用 switch 语句对参数的个数进行了判断,然后调用不同的重载方法: static<E>List<E>of(E...elements){switch(elements.length){//implicitnullcheckofelementscase0:@SuppressWarnings("unchecked")varlist=(List<E>)ImmutableCollections.ListN.EMPTY_LIST;returnlist;case1:returnnewImmutableCollections.List12<>(elements[0]);case2:returnnewImmutableCollections.List12<>(elements[0],elements[1]);default:returnnewImmutableCollections.ListN<>(elements);}} 不管是 ImmutableCollections.List12 还是 ImmutableCollections.ListN,它们都是 final 的,并且继承了 AbstractImmutableList,里面的元素也是 final 的。 staticfinalclassList12<E>extendsImmutableCollections.AbstractImmutableList<E>implementsSerializable{@StableprivatefinalEe0;@StableprivatefinalEe1;}staticfinalclassListN<E>extendsImmutableCollections.AbstractImmutableList<E>implementsSerializable{//EMPTY_LISTmaybeinitializedfromtheCDSarchive.static@StableList<?>EMPTY_LIST;static{VM.initializeFromArchive(ImmutableCollections.ListN.class);if(EMPTY_LIST==null){EMPTY_LIST=newImmutableCollections.ListN<>();}}@StableprivatefinalE[]elements;} 好了,来看一下使用方法吧: finalList<String>unmodifiableList=List.of("沉默王二","沉默王三","沉默王四");unmodifiableList.add("沉默王五"); ImmutableCollections 的内部类 ListN 或者 List12 同样不可修改,使用 add() 方法添加元素同样会在运行时抛出异常: Exceptioninthread"main"java.lang.UnsupportedOperationExceptionatjava.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73)atjava.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:77)atcom.cmower.mkyong.immutablelist.ImmutableListDemo.main(ImmutableListDemo.java:20) 03、借助 Guava Guava 工程包含了若干被 Google 的 Java 项目广泛依赖的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。所有这些工具每天都在被 Google 的工程师应用在产品服务中。 在实际的项目实战当中,Guava 类库的使用频率真的蛮高的,因此我们需要在项目中先引入 Guava 的 Maven 依赖。 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>28.1-jre</version></dependency> Guava 定了一个 ImmutableList 类,它的声明方式如下所示: @GwtCompatible(serializable=true,emulated=true)@SuppressWarnings("serial")//we'reoverridingdefaultserializationpublicabstractclassImmutableList<E>extendsImmutableCollection<E>implementsList<E>,RandomAccess{} 它的类结构关系如下所示: java.lang.Object↳java.util.AbstractCollection↳com.google.common.collect.ImmutableCollection↳com.google.common.collect.ImmutableList ImmutableList 类的 copyOf() 方法可用于创建一个不可变的 List 对象: List<String>list=newArrayList<>(Arrays.asList("沉默王二","沉默王三","沉默王四"));List<String>unmodifiableList=ImmutableList.copyOf(list);unmodifiableList.add("沉默王五"); ImmutableList 同样不允许添加元素,add() 方法在执行的时候会抛出 UnsupportedOperationException 异常: Exceptioninthread"main"java.lang.UnsupportedOperationExceptionatcom.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:244)atcom.cmower.mkyong.immutablelist.ImmutableListDemo.main(ImmutableListDemo.java:25) ImmutableList 类的 of() 方法和 Java 9 的 of() 方法类似,同样有很多相同签名的重载方法,使用方法也完全类似: List<String>unmodifiableList=ImmutableList.of("沉默王二","沉默王三","沉默王四"); ImmutableList 类还提供了 builder 模式,既可以在创建的时候添加元素,也可以基于已有的 List 创建,还可以将两者混合在一起。 ImmutableList<String>iList=ImmutableList.<String>builder().add("沉默王二","沉默王三","沉默王四").build();List<String>list=List.of("沉默王二","沉默王三","沉默王四");ImmutableList<String>iList=ImmutableList.<String>builder().addAll(list).build();List<String>list=List.of("沉默王二","沉默王三","沉默王四");ImmutableList<String>iList=ImmutableList.<String>builder().addAll(list).add("沉默王五").build(); 04、Collections.unmodifiableList() 和 ImmutableList 有什么区别? Collections.unmodifiableList() 基于原有的 List 创建了一个不可变的包装器,该包装器是不可修改的,但是,我们可以通过对原有的 List 进行修改,从而影响到包装器,来看下面的示例: List<String>list=newArrayList<>();list.add("沉默王二");List<String>iList=Collections.unmodifiableList(list);list.add("沉默王三");list.add("沉默王四");System.out.println(iList); 程序输出的结果如下所示: [沉默王二,沉默王三,沉默王四] 但如果我们通过 ImmutableList 类创建一个不可变 List,原有 List 的改变并不会影响到 ImmutableList。 List<String>list=newArrayList<>();list.add("沉默王二");ImmutableList<String>iList=ImmutableList.copyOf(list);list.add("沉默王三");list.add("沉默王四");System.out.println(iList); 程序输出的结果如下所示: [沉默王二] 这是因为 ImmutableList 是在原有的 List 上进行了拷贝。 ------------------ 公众号:沉默王二(ID:cmower)CSDN:沉默王二这是一个有颜值却靠才华吃饭的程序员,你知道,他的文章风趣幽默,读起来就好像花钱一样爽快。 长按下图二维码关注,你将感受到一个有趣的灵魂,且每篇文章都有干货。 ------------------ 原创不易,莫要白票,如果觉得有点用的话,请毫不留情地素质三连吧,分享、点赞、在看,我不挑,因为这将是我写作更多优质文章的最强动力。 本文分享自微信公众号 - 沉默王二(cmower)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。