微信
手机版
网站地图

HIM,堺雅人-科创板首批受理企业名单公布,科创板

2019-07-12 01:09:32 投稿人 : admin 围观 : 225 次 0 评论

△Hollis, 一个对Coding有着共同寻求的人△

调集是Java开发日常开发中经常会运用到的。在之前的一些文章中,咱们介绍过一些关于运用调集类应该留意的事项,关于调集类,《阿里巴巴Java开发手册》中其实还有别的一个规则:

本文就来剖析一下为什么会有如此主张?其背面的原理是什么?


subList

subList是ListHIM,堺雅人-科创板第一批受理企业名单发布,科创板接口中界说的一个办法,该办法首要用于回来一个调集中的一段、能够理解为截取一个调集中的部分元素,他的回来值也是一个List。

如以下代码:

public static void main(String[] args) {
List names = new ArrayList() {{
add("Hollis");
add("hollischuang");
add("H");
}};

List subList = names.subList(0, 1);
System.out.println(subList);
}

以上代码输出成果为:

[Hollis]

假如咱们改动下代码,将subList的回来值强转成ArrayList试一下:

public static void main(String[] args) {
List names = new Array强搂宋祖英List() {{
add("Hollis");
add("hollischuang");
add("H");
}};

ArrayList subList = names.subList(0, 1);
System.out.println(subList);
}

以上代码将抛出反常:

java.lang.ClassCastException:

java.util.ArrayList$SubList cannot be cast to java.util.ArrayList

不仅仅强转成ArrayList会报错,强转成LinkedList、Vector等List的完成类相同也都会报错。

那么,为什么会发作这样的报错呢?咱们接下来深入剖析一下。

底层原理

首要,咱们看下subList办法给咱们回来的List到底是个什么东西,这一点在JDHIM,堺雅人-科创板第一批受理企业名单发布,科创板K源码中注释是这样说的:

Returns a view of the portion of this list between the specifiedfromIndex, inclusive, and toIndex, exclusive.

也就是说subLisroaret 回来是一个视图,那么什么叫做视图呢?

咱们看下subLi吕易圣艾灸液st的源码:

p孙琪琪ublic List subLis隆上记t(int fromInde天算by古镜x, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}

这个办法回来了一个SubList,这个类是A甜姐rrayList中的一个内部类。

SubList这个类中独自界说了set、get、size、add、remove等办法。

当咱们调用subList办法的时分,会经过调用SubList的结构函数创立一个SubList,那么看下这个结构函数做了哪些工作:

SubList(AbstractList parent,
int offset, int fromIndex, int toIndex) {
this.parent = parent;
this.parentOffset = fromIndex;
this.offset = offset + fromIndex;
this.size = toIndex - fromIndex;
this.modCount = ArrayList.this.modCount;
}

能够看到,这个结构函数中把本来的List以及该List中的部分特点直接赋值给自己的一些特点了。

也就是说,SubList并没有从头创立一个List,而是直接引用了原有的List(回来了父类的视图),仅仅赤烛指定了一下儿子射死我他要运用的元素的规模罢了(从fromIndex(包括),飞向甲子园到toIndex(不包括))。

所以,为什么不能讲subList办法得到的调集直接转化成ArrayList呢?由于SubList仅仅ArrayList的内部类,他们之间并没有承继联系,故无法直群狼乱舞接进行强制类型转化。

视图有什么问题

前面经过检查源码,咱们知道,subList()办法并没有从头创立一个ArrayList,而是回来了一个ArrayList的内部类——SubList。

这个SubList是ArrayList的一个视图。

那么,这个视图又会带来什么问题呢?咱们需求简略写几段代码看一下。


1、非结构性改动SubList

public static void main(String[] 盐组词args) {
List so紫琪说的对urceList = new ArrayList() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};

List subList = sourceList.subList(2, 5);

System.out.println("sourceList : " + sourceList);
System.out.println("sourceLi学生搞基st.subList(2, 5) 得到List :");
System.out.println("subList : " + subList);

subList.set(1, "666");

System.out.println("subList.set(3,666) 得到List :");
System.out.println("subList : " + subList);
System.out.println("sourceList : " + sourceList);
}

得到成果:

sourceList[H, O, L, L, I, S]
sourceList.subList(2, 5) 得到List
subList[L, L, I]
subList.set(3,666) 得到List
subList[L, 666, I]
sourceList[H, O, L, 666, I, S]

当咱们测验经过set办法,改动subList中某个元素的值得时分,咱们发现,本来的那个List中对应元素的值也发作了改动。

同理,假如咱们运用相同的办法,对sourceList中的某个元素进行修正,那么subList中对应的值也会发作改动。读者能够自行测验一下。

2、结构性改动SubList

public static void main(String[] args) {
List sourceList = new ArrayList() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};

List subList = sourceList.subList(2, 5);

System.out.println("sourceList : " + sourceList);
System.out.println("sourceList.subList(2, 5) 得到List :");
System.out.println("subLHIM,堺雅人-科创板第一批受理企业名单发布,科创板ist : " + subList);

subList.add("666");

System.out.println("subList.add(666) 得到List :");
System.out.println("subList : " + subList);
System.out.println("sourceList : " + sourceList);

}

得到成果:

sourceList[H, O, L, L, I, S]
sourceList.subList(2, 5) 得到List
subList : HIM,堺雅人-科创板第一批受理企业名单发布,科创板[L, L, I]
subList.add(666) 得到List
subList[L, L, I, 666]
sour了法寺ceList[H, O, L, L, I, 666, S]

咱们测验对subList的结构进行改动,即向其追加元素,那么得到的成果是sourceList的结构也相同发作了改动。

3、结构性改动原List

public static void main(String[] args) {
List sourceList = new ArrayList() {{
add("H");
add("O");
add("L");
add("L");
add("I");
add("S");
}};

List subList = sourceList.subList(2相似师傅不要啊, 5);

System.out.println("sourceList : " + sourceList);
System.out.println("sourceList.subList(2, 5) 得到List :");
System.out.println("subList : " + subList);

sourceList.add("666");

System.out.println("sourceList.add(666) 得到List :");
System.out.println("sourceList : " + sourceList);
System.out.println("subList : " + subList);

}

得到成果:

Exception in thread "main" java.util.ConcurrenHIM,堺雅人-科创板第一批受理企业名单发布,科创板tModificationException
at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1239)
at java.util.ArrayList$SubList.listIterator(ArrayList.java:1099)
at java.util.AbstractList.listIterator(AbstractList.java:299)
at java.util.ArrayList$SubList.iterator(ArrayList.java:1095)
at java.util.AbstractCollection.toString(AbstractCollection.java:454)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at com.hollis.SubListTest.main(SubListTest.java:28)

咱们测验对sourceList的结构进行改动,即向其追加元素,成果发现抛出了ConcurrentModificationException。关于这个反常,咱们在《

一不小心就踩坑的fail-fast是个什么鬼?

》中剖析过,这儿原理相同,就不再赘述了。

小结

咱们简略总结一下,List的subList办法并没有创立一个新的List,而是运用了原List的视图,这个视图运用内部类SubList表明。

所以,咱们不能把subList办法回来的List强制转化成ArrayList等类,由于他们之间没有承继联系。

别的,视图和原LHIM,堺雅人-科创板第一批受理企业名单发布,科创板ist的修正还需求留意陈尔敏几点,尤其是他们之间的相互影响:

  • 1、对父(sourceList)子(subList)List做的非结构性修正(non-structural changes),都会影响到互相。

  • 2、对子List做结构性修正,操作相同会反映到父List上。

  • 3、对父List做结构性修正,会抛出反常ConcurrentModificationException。

所以,阿里巴巴Java开发手册中有别的一条规则:

怎么创立新的List

假如需求对subList作出修正,又不想动原list。那么能够创立subList的一个复制:

subList = Lists.newArrayList(subList);
list.stream().skip(strart).limit(end).collect(Collectors.toList());

PS:最近,《阿里巴巴Java开发手册》现已正式更名为《Java开发手册》,并发布了新版本,增加了21条新规约,修正描绘112处。

参考资料:

https://孙亚峤www.jianshu.com/p/5854851240df https://www.cnblogs.com/ljdblog/起点大神的纲要模板p/6251HIM,堺雅人-科创板第一批受理企业名单发布,科创板387.html


相关文章

标签列表