1、应用Arrays.asList的注意事项
先来看下Arrays.asList的应用:
List<Integer> statusList = Arrays.asList(1, 2); System.out.println(statusList); System.out.println(statusList.contains(1)); System.out.println(statusList.contains(3)); //输入 [1,2] true false //因为这个汇合里没有值为3的这个元素,所以返回false
而后,往statusList中增加元素3,如下所示:
statusList.add(3); System.out.println(statusList.contains(3));
预期的后果,应该是输入true,然而理论却是抛出了java.lang.UnsupportedOperationException
异样:
起因剖析
咱们看下Arrays类提供的静态方法asList的源码:
返回的是ArrayList,然而此ArrayList并非彼ArrayList,咱们平时应用位于java.util包下的ArrayList
,
而此处的ArrayList却是Arrays
类的外部类,它也继承了AbstractList类,重写了很多办法,比方咱们下面应用的contains办法,但并没有实现汇合的批改办法(add/remove/clear)。
所以在调用add办法时才会抛出java.lang.UnsupportedOperationException
异样。
Arrays.asList提现的是适配器模式,只是转换接口,后盾的数据仍是数组。
总结Arrays.asList
办法能够在一些简略的场合应用,比方疾速申明一个汇合,判断某个值是否在容许的范畴内:
2、应用ArrayList的subList的注意事项
先来看下subList的简略应用:
List<String> bookList = new ArrayList<>(); bookList.add("边远的救世主"); bookList.add("背离"); bookList.add("天幕红尘"); bookList.add("人生"); bookList.add("平庸的世界"); List<String> luyaoBookList = bookList.subList(3, 5); System.out.println(bookList); System.out.println(luyaoBookList);
运行后果如下图所示:
从运行后果能够看出,subList返回的是bookList中索引从fromIndex(蕴含)到toIndex(不蕴含)的元素汇合。
应用起来很简略,也很好了解,不过还是有以下几点要留神,否则会造成程序谬误或者异样:
- 批改原汇合元素的值,会影响子集合
- 批改原汇合的构造,会引起ConcurrentModificationException异样
- 批改子集合元素的值,会影响原汇合
- 批改子集合的构造,会影响原汇合
2.1 批改原汇合的值,会影响子集合(同时被批改)
比方,咱们批改下原汇合bookList中某一元素的值(非结构性批改):
//批改bookList 第三个元素值 bookList.set(3,"路遥一人生"); //再输入luyaoBookList值 [路遥一人生,平庸的世界]
能够看出,尽管咱们只是批改了原汇合bookList的值,然而影响到了子集合luyaoBookList。
2.2 批改原汇合的构造,会引起ConcurrentModificationException异样
比方,咱们往原汇合bookList中增加一个元素(结构性批改):
//往原汇合中增加元素 bookList.add("晚上从中午开始"); System.out.println(bookList); System.out.println(luyaoBookList);
能够看出,当咱们往原汇合中增加了元素(结构性批改)后,在遍历子集合时,产生了ConcurrentModificationException
异样。
注意事项:以上异样并不是在增加元素时产生的,而是在增加元素后,遍历子集合时产生的。
对于这一点,在《阿里巴巴Java开发手册》泰山版中是这样形容的:
在subList场景中,高度留神对父汇合元素的减少和删除,均会导致子列表的遍历,减少、删除产生ConCurrentModlficationException异样。
2.3、批改子集合元素的值,会影响原汇合
比方,咱们批改下子集合luyaoBookList中某一元素的值(非结构性批改):
// 批改子集合的值 List<String> luyaoBookList = bookList.subList(3, 5); luyaoBookList.set(1,"路遥-平庸的世界"); //批改了子集合的第二个元素值,同时父汇合的最初一个元素值也被批改 //bookList:[边远的救世王,背离,天幕红尘,人生,路遥-平庸的世界] //luyaoBookList:[人生,平庸的世界]
能够看出,尽管咱们只是批改了子集合luyaoBookList的值,然而影响到了原汇合bookList。
2.4、批改子集合的构造,会影响原汇合
比方,咱们往子集合luyaoBookList中增加一个元素(结构性批改):
List<String> bookList = new ArrayList<>(); bookList.add("边远的救世主"); bookList.add("背离"); bookList.add("天幕红尘"); bookList.add("人生"); bookList.add("平庸的世界"); List<String> luyaoBookList = bookList.subList(3, 5); System.out.println(bookList); System.out.println(luyaoBookList); // 往子集合中增加元素 luyaoBookList.add("晚上从中午开始"); System.out.println(bookList); System.out.println(luyaoBookList);
运行后果如下所示:
能够看出,当咱们往子集合中增加了元素(结构性批改)后,影响到了原汇合bookList。
2.5 起因剖析
首先,咱们看下subList办法的正文,理解下它的用处:
Returns a view of the portion of this list between the specified {@code fromIndex}, inclusive, and {@code toIndex}, exclusive.
译文:
返回指定的{@code fromIndex}(蕴含)和{@code toIndex}(排除)之间的列表局部的视图
而后,咱们看下它的源码:
public List<E> subList(int fromIndex, int toIndex) { subListRangeCheck(fromIndex, toIndex, size); return new SubList(this, 0, fromIndex, toIndex); }
能够看到,它调用了SubList类的构造函数,该构造函数的源码如下图所示:
能够看出,SubList类是ArrayList的外部类,该构造函数中也并没有从新创立一个新的ArrayLis
来源gao!daima.com搞$代!码网
t,所以批改原汇合或者子集合的元素的值,是会相互影响的。
2.6 总结
ArrayList的subList办法,返回的是原汇合的一个子集合(视图),非结构性批改任意一个汇合的元素的值,都会彼此影响,结构性批改原汇合时,会报ConcurrentModificationException
异样,结构性批改子集合时,会影响原汇合,所以应用时要留神,防止程序谬误或者异样。