实战小技巧2:数组与list互转

简介: 这个考题比较常见,也比较简单,难道就这也有什么可以说到的门路不成?接下来本文好好的说一说它的几种实现姿势,总有一款你喜欢的

image.png

每天一个实战小技巧:数组与 list 互转


这个考题比较常见,也比较简单,难道就这也有什么可以说到的门路不成?

接下来本文好好的说一说它的几种实现姿势,总有一款你喜欢的


I. 数组转 List



1. Array.asList


这个考题太简单了,直接使用Array.asList不就完事了么,比如


@Test
public void ary2list() {
    String[] ary = new String[]{ "1", "a"};
    List<String> list = Arrays.asList((ary);
    System.out.println(list);
}
复制代码


数组转 list,so easy!!!

真的就这么简单么???


且看下面这一段代码

public void ary2list() {
    String[] ary = new String[]{ "1", "a"};
    List<String> list = Arrays.asList((ary);
    System.out.println(list);
    list.add("c");
    System.out.println(list);
}
复制代码


直接抛出了异常java.lang.UnsupportedOperationException


有兴趣的小伙伴可以看一下源码实现方式,通过Arrays.asList创建的 List,虽说也命名是ArrayList,但是它的全路径为 java.util.Arrays.ArrayList, 不支持add, remove等操作(所以下次再有面试官问 ArrayList 的知识点时,就可以反问一句,老哥你指的是哪个 ArrayList😝,逼格是不是立马拉起来)


1.1 知识点


  • 通过Arrays.asList创建的列表,不允许新增,删除元素;但是可以更新列表中元素的值


2. new ArrayList


上面的数组转 list 方式虽然是最简单的,但不一定是合适的,特别是当我们可能对转换后的 list 进行操作时,可能埋坑(而且这种坑还非常隐晦,代码层面上很难发现)


为了减少在代码里面下毒的可能性,不妨使用下面这种方式new ArrayList<>(Arrays.asList(ary))

String[] ary = new String[]{ "1", "a"};
List<String> out = new ArrayList<>(Arrays.asList(ary));
out.add("hello");
System.out.println(out);
复制代码


通过上面这种方式创建的 List,就是我们熟知的ArrayList


2.1 避雷预警


看到上面这个使用姿势,就很容易想到一个常见的踩雷点,比如我们的应用中,有一个全局共享的配置列表,张三需要拿 id 为奇数的配置,李四拿 id 为偶数的配置,然后他们都是这么做的


list.removeIf(s -> s.id % 2 == 0);
复制代码


然后跑了一次之后发现这个全局的列表清空了,这就是典型的没有做好资源隔离的 case 了,针对这种场景,要么是限制使用方,直接针对全局的资源进行修改,要么就是使用方拿到的是一个隔离的备份


禁止修改:

  • 使用不可变的容器,如前面提到的java.util.Arrays.ArrayList ()
  • 使用Collections.unmodifiableList创建
List<String> unModifyList = Collections.unmodifiableList(out);
复制代码


列表拷贝

new ArrayList<>(Arrays.asList(ary));
复制代码


(上面这种属于深拷贝的实现,具体可以看一下 jdk 的源码实现)


3. Collections.addAll


第三种方式借助 jdk 提供的容器工具类Collections来实现


@Test
public void ary2listV3() {
    String[] ary = new String[]{ "1", "a"};
    // 创建列表,并指定长度,避免可能产生的扩容
    List<String> out = new ArrayList<>(ary.length);
    // 实现数组添加到列表中
    Collections.addAll(out, ary);
    // 因为列表为我们定义的ArrayList,因此可以对它进行增删改
    out.add("hello");
    System.out.println(out);
}
复制代码


原则上是比较推荐这种方式来实现的,至于为啥?看下源码实现

public static <T> boolean addAll(Collection<? super T> c, T... elements) {
    boolean result = false;
    for (T element : elements)
        result |= c.add(element);
    return result;
}
复制代码


这段代码的实现是不是非常眼熟,如果让我们自己来写,也差不多会写成这样吧,简单直观高效,完美


II. 列表转数组



不同于数组转列表的几种玩法,列表转数组就简单多了,直接调用List.toArray

List<String> list = Arrays.asList("a", "b", "c");
// 返回的是Object[] 数组
Object[] cell = list.toArray();
// 如果需要指定数组类型,可以传一个指定各类型的空的数组
// 也可以传一个与目标列表长度相等的数组,这样会将列表中的元素拷贝到这个数组中
String[] strCell = list.toArray(new String[]{});
复制代码


III. 小结



今天的博文主题是数组与列表的互转,虽说题目简单,但是实现方式也是多种,需要搞清楚它们之间的本质区别,一不小心就可能采坑,而最简单的地方掉坑里,往往是最难发现和爬出来的


核心知识点小结如下


数组转 list:

  • Arrays.asList(xxx):创建的是不可变列表,不能删除和新增元素
  • new ArrayList<>(Arrays.asList(xxx): 相当于用列表创建列表,属于深拷贝的一种表现,获取到的列表支持新增、删除
  • 推荐写法 Collections.addAll()


列表转数组

  • list.toArray: 如果需要指定数组类型,则传参指定



相关文章
|
6月前
|
消息中间件 NoSQL Java
Redis List:打造高效消息队列的秘密武器【redis实战 一】
Redis List:打造高效消息队列的秘密武器【redis实战 一】
263 0
|
6月前
如何实现数组和 List 之间的转换?
如何实现数组和 List 之间的转换?
|
5月前
|
JSON fastjson 数据格式
使用jackson和fastjson实现list与json互转
使用jackson和fastjson实现list与json互转
|
5月前
|
存储 NoSQL 安全
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
Redis第六弹-List列表-(相当于数组/顺序表)Lpush key element-一次可以插入多个元素(假如key已经存在,并且key对应的value并非是list,则会报错)
|
5月前
|
存储 Dart
Dart中的集合类型:List(数组/列表)
Dart中的集合类型:List(数组/列表)
145 0
|
5月前
|
Java 索引
Java List实战:手把手教你玩转ArrayList和LinkedList
【6月更文挑战第17天】在Java中,ArrayList和LinkedList是List接口的实现,分别基于动态数组和双向链表。ArrayList适合索引访问,提供快速读取,而LinkedList擅长插入和删除操作。通过示例展示了两者的基本用法,如添加、访问、修改和删除元素。根据场景选择合适的实现能优化性能。
51 0
|
6月前
|
存储 算法 数据处理
Python中的列表(List) 类型详解与实战应用
Python中的列表(List) 类型详解与实战应用
115 0
|
6月前
字符串和list互转
字符串和list互转
58 0
|
6月前
使用List中的remove方法遇到数组越界
使用List中的remove方法遇到数组越界
103 2
|
6月前
|
存储 索引 Python
多数pythoneer只知有列表list却不知道python也有array数组
多数pythoneer只知有列表list却不知道python也有array数组
65 0