如何打造一个不可变的List集合

如何打造一个不可变的List集合

背景知识
      我们还是拿ArrayList集合举例
      首先我们要知道,ArrayList集合的底层就是一个Object类型的数组(也就是引用类型的数组),并且是default修饰的(也就是只能在java.util包中可以访问)。

transient Object[] elementData;

      我们平常工作中不可能是在java.util包中,所以对于这个数组还是无法直接操作的,需要调用到对应的方法进行操作
      其中在ArrayList集合中就有add、set、remove等添加删除操作的方法。
      我们知道了这些以后就开始打造一个不可变的集合

1、首先是我们不去提供比如add、set、remove等可以对elementData数组进行添加删除的操作方法。
      其中java的Collections集合工具类就提供了一个unmodifiableList的方法

 ArrayList<Object> list = new ArrayList<>();
 List<Object> unModifiAbleList = Collections.unmodifiableList(list);

      这个方法的原理就是根据ArrayList中的elementData数组创建一个不提供增删改方法的集合。
      但是这个集合还是有缺陷的,继续往下看。
2、会发现通过unModifiAbleList 是不能更改集合内容了,但是还可以通过之前的list进行unModifiAbleList 内容的更改,
      原因就是,unModifiAbleList 和list里面都是使用的同一个储存数据的数组对象。
      解决方法一
      创建完unModifiAbleList 对象后,将之前的list引用对象指向null。
      后面list就无法影响unModifiAbleList 的内容了,

 ArrayList<Object> list = new ArrayList<>();
 List<Object> unModifiAbleList = Collections.unmodifiableList(list);
 list = null;

      但是这种还是有缺陷的。如下面这种情况,list2 或者list3 的操作仍旧会影响unmodifiableList的内容

ArrayList<Object> list = new ArrayList<>();
List list2 = list;
List list3 = list;
List<Object> unModifiAbleList = Collections.unmodifiableList(copyList);
list = null;

      解决方法二
      操作就是将list的内容进行复制。
      代码如下

ArrayList<Object> list = new ArrayList<>();
ArrayList<Object> copyList = new ArrayList<>(Arrays.asList(new Object[10]));
Collections.copy(copyList,list);
List<Object> unModifiAbleList = Collections.unmodifiableList(copyList);
copyList = null;

      这样我们的unModifiAbleList 就更加完善了。
      还可以进一步优化。

3、将上面的思路封装
      封装获取不变集合的方法

 public static List getUnModifiAbleList(List list) {
        ArrayList<Object> copyList = new ArrayList<>(Arrays.asList(new Object[list.size()]));
        Collections.copy(copyList,list);
        List<Object> unModifiAbleList = Collections.unmodifiableList(copyList);
        copyList = null;
        return unModifiAbleList;
    }

      方法内的copyList = null;是可以去掉的。
      不变集合方法的使用

ArrayList<Object> list = new ArrayList<>();
List unModifiAbleList = getUnModifiAbleList(list);

      这样获取到的unModifiAbleList 就更加完美了。
      但是还是有一点缺陷
4、虽然堆内存的内容无法修改了,但是我们还可以修改unModifiAbleList 的指针指向,达到unModifiAbleList 内容的全部更改。
      于是,我们在用final对unModifiAbleList 进行修饰。

 ArrayList<Object> list = new ArrayList<>();
 final List unModifiAbleList = getUnModifiAbleList(list);

      大功告成,真正的不可变集合创建出来了。

5、如果你不想这么麻烦的去操作,Guava immutable list也是一个不错的选择,其原理也是和上面的思路大同小异。
      代码操作如下:

ImmutableList.copyof(list);

6、后序—等以后有时间了在深入说这两点吧。

  1. 也可以根据自己的需求,自己写一个自定义不变集合。(不在使用Collections创建的不可变集合)
  2. 集合复制方面是还可以继续优化的。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值