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,都是不可修改的。

public static List unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new Collections.UnmodifiableRandomAccessList<>(list) :
new Collections.UnmodifiableList<>(list));
}
来看一下使用方法:

List list = new ArrayList<>(Arrays.asList(“沉默王二”, “沉默王三”, “沉默王四”));
List unmodifiableList = Collections.unmodifiableList(list);
我们尝试往 unmodifiableList 中添加元素“沉默王五”:

unmodifiableList.add(“沉默王五”);
运行后会抛出 UnsupportedOperationException 异常:

Exception in thread “main” java.lang.UnsupportedOperationException
at java.base/java.util.Collections$UnmodifiableCollection.add(Collections.java:1062)
at com.cmower.mkyong.immutablelist.ImmutableListDemo.main(ImmutableListDemo.java:16)
02、借助 Java 9
Java 9 的时候,List 类新增了一个 of() 静态工厂方法,可以用来创建不可变的 List。先来看一下源码:

static List of(E e1, E e2, E e3) {
return new ImmutableCollections.ListN<>(e1, e2, e3);
}
of() 方法有很多变体,比如说:

static List of(E e1) {
return new ImmutableCollections.List12<>(e1);
}
static List of(E e1, E e2) {
return new ImmutableCollections.List12<>(e1, e2);
}
static List of(E e1, E e2, E e3, E e4) {
return new ImmutableCollections.ListN<>(e1, e2, e3, e4);
}
static List of(E e1, E e2, E e3, E e4, E e5) {
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5);
}
static List of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
return new ImmutableCollections.ListN<>(e1, e2, e3, e4, e5,
e6, e7, e8, e9, e10);
}
该方法的设计者也挺有意思的,of() 方法的参数,从 0 到 10 都有一个相同签名的重载方法。

甚至当参数是可变的时候,使用 switch 语句对参数的个数进行了判断,然后调用不同的重载方法:

static List of(E… elements) {
switch (elements.length) { // implicit null check of elements
case 0:
@SuppressWarnings(“unchecked”)
var list = (List) ImmutableCollections.ListN.EMPTY_LIST;
return list;
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
不管是 ImmutableCollections.List12 还是 ImmutableCollections.ListN,它们都是 final 的,并且继承了 AbstractImmutableList,里面的元素也是 final 的。

static final class List12 extends ImmutableCollections.AbstractImmutableList
implements Serializable {

@Stable
private final E e0;@Stable
private final E e1;

}

static final class ListN extends ImmutableCollections.AbstractImmutableList
implements Serializable {

// EMPTY_LIST may be initialized from the CDS archive.
static @Stable List<?> EMPTY_LIST;static {VM.initializeFromArchive(ImmutableCollections.ListN.class);if (EMPTY_LIST == null) {EMPTY_LIST = new ImmutableCollections.ListN<>();}
}@Stable
private final E[] elements;

}
好了,来看一下使用方法吧:

final List unmodifiableList = List.of(“沉默王二”, “沉默王三”, “沉默王四”);
unmodifiableList.add(“沉默王五”);
ImmutableCollections 的内部类 ListN 或者 List12 同样不可修改,使用 add() 方法添加元素同样会在运行时抛出异常:

Exception in thread “main” java.lang.UnsupportedOperationException
at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:73)
at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:77)
at com.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 依赖。

com.google.guava guava 28.1-jre Guava 定了一个 ImmutableList 类,它的声明方式如下所示:

@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings(“serial”) // we’re overriding default serialization
public abstract class ImmutableList extends ImmutableCollection
implements List, RandomAccess {
}
它的类结构关系如下所示:

java.lang.Object
↳ java.util.AbstractCollection
↳ com.google.common.collect.ImmutableCollection
↳ com.google.common.collect.ImmutableList
ImmutableList 类的 copyOf() 方法可用于创建一个不可变的 List 对象:

List list = new ArrayList<>(Arrays.asList(“沉默王二”, “沉默王三”, “沉默王四”));
List unmodifiableList = ImmutableList.copyOf(list);
unmodifiableList.add(“沉默王五”);
ImmutableList 同样不允许添加元素,add() 方法在执行的时候会抛出 UnsupportedOperationException 异常:

Exception in thread “main” java.lang.UnsupportedOperationException
at com.google.common.collect.ImmutableCollection.add(ImmutableCollection.java:244)
at com.cmower.mkyong.immutablelist.ImmutableListDemo.main(ImmutableListDemo.java:25)
ImmutableList 类的 of() 方法和 Java 9 的 of() 方法类似,同样有很多相同签名的重载方法,使用方法也完全类似:

List unmodifiableList = ImmutableList.of(“沉默王二”, “沉默王三”, “沉默王四”);
ImmutableList 类还提供了 builder 模式,既可以在创建的时候添加元素,也可以基于已有的 List 创建,还可以将两者混合在一起。

ImmutableList iList = ImmutableList.builder()
.add(“沉默王二”, “沉默王三”, “沉默王四”)
.build();

List list = List.of(“沉默王二”, “沉默王三”, “沉默王四”);
ImmutableList iList = ImmutableList.builder()
.addAll(list)
.build();

List list = List.of(“沉默王二”, “沉默王三”, “沉默王四”);
ImmutableList iList = ImmutableList.builder()
.addAll(list)
.add(“沉默王五”)
.build();
04、Collections.unmodifiableList() 和 ImmutableList 有什么区别?
Collections.unmodifiableList() 基于原有的 List 创建了一个不可变的包装器,该包装器是不可修改的,但是,我们可以通过对原有的 List 进行修改,从而影响到包装器,来看下面的示例:

List list = new ArrayList<>();
list.add(“沉默王二”);

List iList = Collections.unmodifiableList(list);

list.add(“沉默王三”);
list.add(“沉默王四”);

System.out.println(iList);
程序输出的结果如下所示:

[沉默王二, 沉默王三, 沉默王四]
但如果我们通过 ImmutableList 类创建一个不可变 List,原有 List 的改变并不会影响到 ImmutableList。

List list = new ArrayList<>();
list.add(“沉默王二”);

ImmutableList iList = ImmutableList.copyOf(list);

list.add(“沉默王三”);
list.add(“沉默王四”);

System.out.println(iList);
程序输出的结果如下所示:

[沉默王二]
这是因为 ImmutableList 是在原有的 List 上进行了拷贝。
Absorbing material: www.goodsmaterial.com

Immutable List相关推荐

  1. java string改变的影响_为什么Java的string类要设成immutable(不可变的)

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  2. Java并发设计模式--不可变模式(immutable)

    一.什么是不可变模式? 不可变,顾名思义,就是对象创建之后就不能够变化嘛!更具体地说,就是对象创建之后它的属性值不能够发生变化!所有对原对象的操作都会返回原对象的拷贝.那么在java中怎么做到这一点呢 ...

  3. PostgreSQL Oracle 兼容性之 - PL/SQL DETERMINISTIC 与PG函数稳定性(immutable, stable, volatile)...

    标签 PostgreSQL , Oracle , 函数稳定性 , stable , immutable , volatile , DETERMINISTIC 背景 Oracle创建pl/sql函数时, ...

  4. Java多线程编程模式实战指南(二):Immutable Object模式--转载

    本文由本人首次发布在infoq中文站上:http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-o ...

  5. 多线程:Immutable对象?如何创建Immutable对象?

    那么什么是immutable objects?什么又是mutable Objects呢? immutable Objects就是那些一旦被创建,它们的状态就不能被改变的Objects,每次对他们的改变 ...

  6. Redux vs Mobx系列(-):immutable vs mutable

    **注意:**我会写多篇文章来比较说明redux和mobx的不同,redux和mobx各有优缺点, 如果对React/Mobx/Redux都理解够深刻,我个人推荐Mobx(逃跑...) React社区 ...

  7. Immutable 想破坏它也没办法

    上一章讲的是线程互斥的synchronized实现,这样做会影响性能,如何才能做到既不影响性能又能达到线程安全的目的呢,就是使用状态绝不会改变的类,Java中的应用就是String类. public ...

  8. 关于[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object的报错分析

    首先,我们来分析一下这个报错的主要意思 mutating method sent to immutable object 说的是一个不可变的对象使用了可变的方法. 这里面也许很多人会感到奇怪,我数组明 ...

  9. leetcode 304. Range Sum Query 2D - Immutable |304. 二维区域和检索 - 矩阵不可变(二维前缀和问题)

    题目 https://leetcode.com/problems/range-sum-query-2d-immutable/ 题解 本题是 medium 难度,二维前缀和问题.相似题目有: Easy: ...

  10. java中 immutable,future,nio

    什么是Future? 用过Java并发包的朋友或许对Future (interface) 已经比较熟悉了,其实Future 本身是一种被广泛运用的并发设计模式,可在很大程度上简化需要数据流同步的并发应 ...

最新文章

  1. c++循环执行一个函数_20川大计算机 | 时间复杂度,你避不开的一个考点
  2. 介绍两个好玩的和Github相关的Chrome扩展 1
  3. 开关 关闭_无论用什么品牌手机,这个开关要关闭,以免耗电又卡顿,抓紧试试...
  4. 背景调查 跳槽_分享 | 录用背景调查,查的到底是什么?
  5. 织梦缩略图自动补齐绝对路径_织梦生成文章内容缩略图时自动加上域名绝对路径...
  6. Call for Papers | ACCV 2022在澳门等你
  7. python精彩编程200例-200G的Python初高级教程+项目实战案例源码,让你做有钱途的人才...
  8. 算法题在我看来都是小意思
  9. 存图方式---邻接表邻接矩阵前向星
  10. 在win7的操作系统下安装Oracle11R2
  11. Pipeline aborted due to error
  12. 压缩word的简单方法看这里
  13. AutoCAD 2007打开慢
  14. Zero-Shot Deep Domain Adaptation[reading notes]
  15. 解决SSLHandshakeException :sun.security.validator.ValidatorException: PKIX path building failed:
  16. 压缩软件大评比,7-ZIP/WinZIP/WinRAR的抗争
  17. 利用grub引导多系统debian8.0+win7+ubuntu16.04
  18. 面试官,你到底安的什么心?
  19. pandas取整 pandas取整数 pandas 转成int
  20. htb_Escape (mssql渗透,winrm)

热门文章

  1. 社区团购系统和运作模式
  2. 跟测试老兵3天成为APP高手(三)
  3. 学习Windows Phone 7手机开发:迷你手电筒程序
  4. SCAU 17968 Takio与Blue的人生赢家之战
  5. Observability:使用 Elastic Agent 来进行 Uptime 监控
  6. gcc 编译引用头文件
  7. python画画用哪个软件_如何用python画韦恩图? 使用python的tutul工具,画一朵雏菊花...
  8. 华为鸿蒙使用怎么样,华为鸿蒙平板详情-华为鸿蒙平板怎么样
  9. 静图怎么做成gif动画图片?三步教你在线生成gif图片
  10. ORACLE AME