Java List接口的内容有哪些及如何使用
今天小编给大家分享一下Java List接口的内容有哪些及如何使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
前言List接口是Collection接口的三大接口之一,其中的数据可以通过位置检索,用户可以在指定位置插入数据。List的数据可以为空,可以重复。
一、List特有的方法我们这里就只关注和Collection不同的方法,主要有以下这些:
//在指定位置,将指定的集合插入到当前的集合中booleanaddAll(intindex,Collection<?extendsE>c);//这是一个默认实现的方法,会通过Iterator的方式对每个元素进行指定的操作defaultvoidreplaceAll(UnaryOperator<E>operator){Objects.requireNonNull(operator);finalListIterator<E>li=this.listIterator();while(li.hasNext()){li.set(operator.apply(li.next()));}}//排序,依据指定的规则对当前集合进行排序,可以看到,排序是通过Arrays这个工具类完成的。defaultvoidsort(Comparator<?superE>c){Object[]a=this.toArray();Arrays.sort(a,(Comparator)c);ListIterator<E>i=this.listIterator();for(Objecte:a){i.next();i.set((E)e);}}//获取指定位置的元素Eget(intindex);//修改指定位置元素的值Eset(intindex,Eelement);//将指定元素添加到指定的位置voidadd(intindex,Eelement);//将指定位置的元素移除Eremove(intindex);//返回一个元素在集合中首次出现的位置intindexOf(Objecto);//返回一个元素在集合中最后一次出现的位置intlastIndexOf(Objecto);//ListIterator继承于Iterator,主要增加了向前遍历的功能ListIterator<E>listIterator();//从指定位置开始,返回一个ListIteratorListIterator<E>listIterator(intindex);//返回一个子集合[fromIndex,toIndex),非结构性的修改返回值会反映到原表,反之亦然。//如果原表进行了结构修改,则返回的子列表可能发生不可预料的事情List<E>subList(intfromIndex,inttoIndex);
通过对上面方法的研究,我们不难发现,collection接口主要提供一些通常的方法,而List接口则针对线性表的结构,提供了对位置以及字表的操作。
二、超级实现类AbstractList我们先看看源文档是怎么来说AbstractList的,要实现一个不可修改的集合,只需要复写get和size方法。如果要实现一个可以修改的集合,还需要复写set方法,如果要动态调整大小,就必须实现add和remove方法。
接下里我们一起来来看看源码吧!
//在AbstractCollection中,add方法默认会抛出异常,//而在这里是调用了add(intindex,Ee)方法,但这个方法也是没有实现的。//这里默认会把元素添加到末尾。publicbooleanadd(Ee){add(size(),e);returntrue;}//同上,这个只需要进行一次遍历即可publicbooleanaddAll(intindex,Collection<?extendsE>c){//...}
接下里我们在继续看看其他几个方法,这几个是与Iterator和ListIterator息息相关的,在AbstractList中有具体的实现,我们先来看看它是如何把集合转变成Iterator对象并支持foreach循环的吧。
我们通过源码发现:在Iterator方法中,是直接返回一个 Itr对象
publicIterator<E>iterator(){returnnewItr();}
其实我们很快也就会明白,它是实现了一个内部类,这个内部类实现了Iterator接口,合理的处理hasNext、next、remove方法。这个源码就不粘贴啦,其中仅仅在remove时考虑了一下多线程问题,有兴趣的可以自己去看看。
我们来看看另一个吧–ListIterator吧他也是通过一个内部类是实现的
publicListIterator<E>listIterator(){returnlistIterator(0);}
publicListIterator<E>listIterator(finalintindex){rangeCheckForAdd(index);returnnewListItr(index);}
事实证明,和我们想的一样,AbstractList内部还定义了一个ListItr,实现了ListIterator接口,其实现也很简单,就不粘贴源码啦。
接下俩让我们来看看AbtractList是怎么利用这两个类来做事情的
//寻找一个元素首次出现的位置,只需要从前往后遍历,找到那个元素并返回其位置即可。publicintindexOf(Objecto){ListIterator<E>it=listIterator();if(o==null){while(it.hasNext())if(it.next()==null)returnit.previousIndex();}else{while(it.hasNext())if(o.equals(it.next()))returnit.previousIndex();}return-1;}//同理,寻找一个元素最后一次出现的位置,只需要从列表最后一位向前遍历即可。//看到listIterator(intindex)方法是可以传递参数的,这个我想我们都可以照着写出来了。publicintlastIndexOf(Objecto){//...}//这个方法是把从fromIndex到toIndex之间的元素从集合中删除。//clear()方法也是调用这个实现的(我认为clear实现意义并不大,因为在其上级AbstractCollection中已经有了具体实现)。protectedvoidremoveRange(intfromIndex,inttoIndex){ListIterator<E>it=listIterator(fromIndex);for(inti=0,n=toIndex-fromIndex;i<n;i++){it.next();it.remove();}}
在接下来让我们来说一说两个比较重要的内容一个是关于SubList,另一个是关于equals和hascode的。
三、SubList、equals和hascodeSubList并不是新建了一个list,只是持有当前集合的引用,然后控制了用户可以操作的范围,所以在接口定义时就说明了其更改会直接反应到原集合中。SubList是定AbstractList内部,并且是AbstractList的基础上增加了对可选范围的控制。
而equals和hascode的实现,也关乎我们的使用。在AbstractList中,这两个方法不仅与其实例有关,也和其内部包含的元素有关,所以在定义数据元素时,也应该复写这两个方法,以保证程序的正确运行。这里看下其源码加深一下印象吧。
publicbooleanequals(Objecto){if(o==this)returntrue;if(!(oinstanceofList))returnfalse;ListIterator<E>e1=listIterator();ListIterator<?>e2=((List<?>)o).listIterator();while(e1.hasNext()&&e2.hasNext()){Eo1=e1.next();Objecto2=e2.next();//这里用到了数据元素的equals方法if(!(o1==null?o2==null:o1.equals(o2)))returnfalse;}return!(e1.hasNext()||e2.hasNext());}
publicinthashCode(){inthashCode=1;for(Ee:this)//这里用到了数据元素的hashCode方法hashCode=31*hashCode+(e==null?0:e.hashCode());returnhashCode;}
以上就是“Java List接口的内容有哪些及如何使用”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。