Java中List.of与Arrays.asList的区别

布鸽不鸽 Lv4

前言

Java中List.of和Arrays.asList都可以用来快速创建一个List容器

在Java中List.ofArrays.asList都可以用来快速创建一个List容器

1
2
3
// 直接创建
List<Integer> list1 = List.of(1, 2, 3);
List<Integer> list2 = Arrays.asList(1, 2, 3);
1
2
3
4
// 从数组创建
Integer[] ints = {4, 5, 6};
List<Integer> list1 = List.of(ints);
List<Integer> list2 = Arrays.asList(ints);

原文地址:https://xuedongyun.cn/post/8447/

区别

List.ofArrays.asList的区别在于:

List.ofArrays.asList
能否包含null不可以可以
能否修改不可以可以
修改原数组是否影响List不影响影响

List.of不能包含null的原因

  • List.of源代码中明确有写,不能包含null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@SafeVarargs
@SuppressWarnings("varargs")
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
@SuppressWarnings("unchecked")
var list = (List<E>) ImmutableCollections.EMPTY_LIST;
return list;
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return ImmutableCollections.listFromArray(elements);
}
}
1
2
3
4
5
6
7
8
9
10
@SafeVarargs
static <E> List<E> listFromArray(E... input) {

E[] tmp = (E[])new Object[input.length];
for (int i = 0; i < input.length; i++) {
// 元素不能为null,否则抛出错误
tmp[i] = Objects.requireNonNull(input[i]);
}
return new ListN<>(tmp, false);
}

List.of不能修改的原因

1
2
3
4
5
6
7
8
// 底层存储的数组用final修饰
@Stable
private final E[] elements;

private ListN(E[] elements, boolean allowNulls) {
this.elements = elements;
this.allowNulls = allowNulls;
}

原数组是否影响List的原因

List.of而言,底层创建了新的new Object[],所以修改数组不影响List

1
2
3
4
5
6
7
8
9
10
@SafeVarargs
static <E> List<E> listFromArray(E... input) {
// 新建了数组,并复制了值
E[] tmp = (E[])new Object[input.length];
for (int i = 0; i < input.length; i++) {
// 元素不能为null,否则抛出错误
tmp[i] = Objects.requireNonNull(input[i]);
}
return new ListN<>(tmp, false);
}

Arrays.asList而言,直接使用了传入的数组作为底层存储,所以修改数组影响List

1
2
3
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
1
2
3
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
1
2
3
4
5
6
// 只要传入的数组不是null就行
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}

Arrays.asList常见错误

Arrays.asList修改

Arrays.asList()返回的是一个固定大小的List,这个List对象是通过Arrays内部类ArrayList(也叫ArrayList!)创建的

这个List不支持修改元素大小(add和remove方法),修改会报异常: java.lang.UnsupportedOperationException

原因:Arrays内部类ArrayList其实是直接使用了原始的数组,因为共享了数组,相互修改容易产生 Bug

1
2
3
4
List<Integer> list = Arrays.asList(1, 2, 3);

// 报错:UnsupportedOperationException
list.add(222);

解决方法1:使用ArrayList来进行转换

1
2
3
Integer[] ints = {1, 2, 3};
List<Integer> list = Arrays.asList(ints);
ArrayList<Integer> list1 = new ArrayList<>(list);

解决方法2:使用Collections.addAll()

1
2
3
Integer[] ints = {1, 2, 3};
ArrayList<Integer> list = new ArrayList<>(ints.length);
Collections.addAll(list, ints);

解决方法3:使用Stream

1
2
Integer[] ints = {1, 2, 3};
List<Integer> list = Stream.of(ints).toList();

原生类型数组作为参数

asList方法的签名为:public static <T> List<T> asList(T... a),需要匹配参数类型T,但是原生属性是没有这个类型的。所以当传入一个原生数据类型数组时,asList得到的真正参数不是数组中的元素,而是数组本身!

1
2
3
4
int[] ints = {1, 2, 3};

// 创建的List的元素类型为int[],而不是int
List<int[]> list = Arrays.asList(ints);

解决方法:使用包装类数组

1
2
Integer[] ints = {1, 2, 3};
List<Integer> list = Arrays.asList(ints);
  • 标题: Java中List.of与Arrays.asList的区别
  • 作者: 布鸽不鸽
  • 创建于 : 2023-07-16 17:06:18
  • 更新于 : 2023-08-28 15:42:52
  • 链接: https://xuedongyun.cn//post/8447/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论