你以为的 List 就是你以为的 List 吗?

最近接手一个同事的代码,返回一个 list,我在添加数据时提示 UnsupportedOperationException 这个报错是提示不支持的操作,为什么不支持呢?往上翻代码发现传过来的 list 是这样的 Arrays.asList(1,2); 看到这个报错就明白了,下面详细说说。

几种 list 的创建方式:


1、通过 new 对象的方式

List<Integer> list = new ArrayList<>();
// 最常用的方式,可以理解为是一个标准 List 
// 源码就不看了,应该都看过了

2、使用匿名内部类

List<Integer> list = new ArrayList<>() {{
    add(1);
    add(2);
}};
// 原理同上,只是使用了匿名内部类

3、通过 Arrays 创建

List<Integer> list = Arrays.asList(1,2);
// 参数是可变长度的
// 使用:没有增删操作的场景,如 接口直接返回

下图是源码,asList() 返回一个 ArrayList,这样看似没什么不同,但你仔细看返回的这个 ArrayList 是 Arrays 的一个私有内部类,并非常用的那个 ArrayList,虽然同样继承自 AbstractList,但这个 ArrayList 内部并没有重写 add() 方法(没有重写父类的方法,执行 add() 时会去调用父类的 add(),AbstractList里面的add() 直接抛出一个 UnsupportedOperationException 不支持的操作),只有几个简单的函数。

作为设计者去写一个类为内部类,肯定是希望只有内部调用,而非公开使用。

image.png

4、使用 Collections 创建一个单数据 List

List<Integer> list = Collections.singletonList(1);
// 也是一个常用方式,参数只有一个,内部数据也只有一个

下图 SingletonList 同样也是一个私有内部类,同样继承自 AbstractList,同样没有重新 add() 函数,所以同样不支持 add() 操作。还有一个注意的点,因为是单个数据的 list,它的 size() 返回 1。

image.png

5、使用 Stream 流创建 List

List<Integer> list = Stream.of(1, 2, 3).collect(toList());
// 下面是 collect(toList()) 的 toList()

Stream 是 JDK1.8 推出的,1.8 以下的版本不支持这种方式,这里要看 toList() 函数。可以看到源码也是使用 new ArrayList,然后调用 add() 方法依次添加的。

image.png

6、使用 List 接口的静态的方法

List<Integer> list = List.of(1, 2, 3);
// 接口的静态的方法,也称默认函数

返回了 new ImmutableCollections.List12<>(e1)

ImmutableCollections 是一个不可变集合 既然不可变,说明也是不能 add 的。

不过有一点,既然有可变参数函数 static <E> List<E> of(E... elements),为什么还要每不同参数数量都要写一个函数呢,虽然再往下,一个是 List12 一个是 ListN,但里面实现也差不多

image.png

7、使用 Collections 集合创建一个空的 list

List<Integer> list = Collections.emptyList();
// 返回一个空的 List,不可变,也是不能 add 的

这大概是防止报错用的吧…hhh 实际真的就是防止报错用的。你可能会想用 new ArrayList<>() 不也一样吗? 不一样!

new ArrayList<>() 是构造一个初始容量为 10 的空列表。
Collections.emptyList()  返回的是 EmptyList(空数组), 减少了内存开销

image.png

8、使用 Collections 集合创建带副本的 list

/**
 * 参数 n :重复多少个o
 * 参数 o :要添加的元素
 */
List<Integer> list = Collections.nCopies(n, o);

例子:
// list 里面有3个元素,3个元素都是 1
// [1, 1, 1]
List<Integer> list = Collections.nCopies(3, 1);

// list 里面有4个元素,4个元素都是 "AAA"
// ["AAA", "AAA", "AAA", "AAA"]
List<String> list = Collections.nCopies(4, "AAA");

同样是私有的内部类,继承了 AbstractList 没有重写 add() 方法,注释提示,与 list.addAll() 配合服用效果更佳哦。

image.png

总结

今天不总结,上面都说明白了,再看不明白出来挨打! 下班!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值