嗨~ 大家周末欢快啊,我是阿壮,一个 Java 程序员,最近在工作之余,即没 bug 要改了,也没需要了,又不能让老板看到本人在摸鱼,无聊的我开始 ctrl+ 鼠标左键,漫无目的的看着眼前的 JDK 源码。明天来更大家分享以下我遇到过的 java.util.Arrays
下的坑。
次要剖析三个问题,并给出对于的解决方案
- 通过 asList 返回的固定大侠的 List 不反对增加元素
- 对原始数组的批改会影响到咱们取得的那个 List
- 不能间接应用 Arrays.asList 来转换根本类型数组
请容许我应用巨佬 Java 之父 James Gosling 写的 JDK 源码作为明天的开始。
通过 asList 返回的固定大侠的 List 不反对增加元素
代码
public static void main(String[] args) {String[] arr = new String[]{"aa", "bb"};
List<String> list = Arrays.asList(arr);
list.add("cc");
}
执行后果
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at Test.main(Test.java:8)
起因是 java.util.Arrays.ArrayList 类实现了 set(),get(),contains()办法,然而并没有实现减少元素的办法(事实上是能够调用 add 办法,然而没有具体实现,仅仅抛出 UnsupportedOperationException 异样),因而它的大小也是固定不变的。能够通过 set 办法进行设置值,默认长度是 10。
解决方案
新建一个 ArrayList
代码:
public static void main(String[] args) {String[] arr = {"aa", "bb", "cc"};
List<String> list = Arrays.asList(arr);
ArrayList<String> strings = new ArrayList<>(list);
strings.add("dd");
System.out.println(strings.toString());
}
执行后果:
[aa, bb, cc, dd]
通过汇合工具类 Collections.addAll()办法(最高效,举荐)
通过 Collections.addAll(arrayList, strArray)形式转换,依据数组的长度创立一个长度雷同的 List,而后通过 Collections.addAll()办法,将数组中的元素转为二进制,而后增加到 List 中,这是最高效的办法。
代码:
public static void main(String[] args) {String[] arr = {"aa", "bb", "cc"};
ArrayList<String> strings = new ArrayList<>(arr.length);
Collections.addAll(strings, arr);
strings.add("dd");
System.out.println(strings.toString());
}
执行后果:
[aa, bb, cc, dd]
Stream 优雅的写法
代码:
public static void main(String[] args) {String[] arr = {"aa", "bb", "cc"};
List<String> list = Stream.of(arr).collect(Collectors.toList());
list.add("dd");
System.out.println(list.toString());
}
执行成果:
[aa, bb, cc, dd]
底层先将数组转换为流,再应用 addAll()的形式,执行效率次于 Collections.addAll()
形式,然而写法优雅呀。
对原始数组的批改会影响到咱们取得的那个 List
代码
public static void main(String[] args) {String[] arr = {"aa", "bb", "cc"};
List<String> list = Arrays.asList(arr);
arr[1] = "dd";
System.out.printf("arr:%s list:%s", Arrays.toString(arr), list);
}
执行后果
arr:[aa, dd, cc] list:[aa, dd, cc]
起因是 Arrays 外部类 ArrayList 其实是间接应用了原始的数组,把通过 Arrays.asList 取得的 List 交给其余办法解决,很容易因为共享了数组,互相批改产生 Bug。
不能间接应用 Arrays.asList 来转换根本类型数组
代码
public static void main(String[] args) {int[] arr = {1, 2, 3};
List list = Arrays.asList(arr);
System.out.println(list.size());
}
执行后果
1
起因是 asList 办法的参数必须是对象或者对象数组,而原生数据类型不是对象,当传入一个原生数据类型数组时,asList 的真正失去的参数就不是数组中的元素,而是数组对象自身。
解决方案
Java8 可通过 stream 流将 3 种根本类型数组转为 List
如果 JDK 版本在 1.8 以上,能够应用流 stream 来将下列 3 种数组疾速转为List
,别离是int[]
、long[]
、double[]
,其余数据类型比方short[]
、byte[]
、char[]
,在 JDK1.8 中暂不反对。
代码:
public static void main(String[] args) {int[] arr = {1, 2, 3};
List<Integer> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
System.out.println(list);
}
执行成果:
[1, 2, 3]
我是阿壮,一个后端程序员,微信搜一搜:科技猫,继续分享原创编程技术,实用软件,科技资讯,咱们下期间