13 年技术老兵用半首歌的时间,告诉你,Java 还有不可变 List:Immutable List

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(“沉默王二”);

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(“沉默王二”);

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值