您的位置:首页 > 编程语言 > Java开发

关于Java的List的笔记

2016-07-21 19:06 477 查看

1.前言

曾经对于Java的集合类感觉特别迷茫,各种奇葩的设计简直令人摸不着头脑,最近打算好好抓抓基础,就重新研究研究这个问题,这里我就不再过多的研究源码,主要研究他们的继承关系,这里我就分为三类来研究-set、map和list。我会在每一个当中选取我主要常用的加以了解,这里主要是作为笔记来使用的,因此不会出现过多的理解的知识。

2.正文

这里我们首先看下《thinking in Java》中对于新集合类的类图的表述,个人感觉这个很重要。但是我想如果你不是很了解对这个图简直摸不着头脑。



2-1关于循环

这里我们大概了解下Iterator.这是一个为了循环Collection的一个设计,他类似于C语言的链表,可以实现迭代器模式。主要是隐藏了里面的遍历细节,是程序员无需关心实现细节(ps我早需求中没遇到过这种问题,本人也不太明白,不过感觉在数据结构复杂的时候。可以帮助解决里面的问题。比如如果集合中的元素是集合,那么久可以实现递归调用了,如果没有这个设计,直接通过循环感觉稍显复杂。逻辑不清晰)。为了使集合可以实现Iterator。我们一般是集合实现Iterable接口。而事实确实如此。Java的Collection确实实现了Iterable接口

public interface Collection<E> extends Iterable<E> {
......
}


我想大家比较关心最多的是效率问题。对于选择用循环还是用迭代器,这里我也在纠结。有一篇博客说的是官方建议是:(他研究了这个问题研究的比较好)

JDK中说的很清楚,在对List特别是Huge size的List的遍历算法中,要尽量来判断是属于RandomAccess(如ArrayList)还是Sequence List (如LinkedList),因为适合RandomAccess List的遍历算法,用在Sequence List上就差别很大。

这里我还是大概研究研究这个问题吧,因为确实我们会遇到选择困难症的童鞋,当然我也有这个病。这里主要有三种遍历数组的方法

ArrayList< Integer> list = new ArrayList<>();
//第一种
Iterator iterator = list.iterator();
while (iterator.hasNext()){
a = (Integer)iterator.next()+a;
}
//第二种
for (Integer b : linkedList){
a = a+b;
}
}
//第三种
for (int i = 0 ; i< list.size();i++){
a = 3+(int)list.get(i);
}


关于这三种方法,貌似前两种貌似是一种实现原理,具体我也不太清楚,但是我们立马回发现这种写法更简单。我自己又写了例子测试下,数据量为100w条。在arraylist(实现RandomAccess接口)在任何一种遍历总基本一样。在LinkedList(未实现RandomAccess接口)。我分别中了三种方法遍历其中五个数据基本不变。但是有一种是个bug–我一度以为是我代码写的有问题–通过第三种循环LinkedList。遍历很久。其他大概都是10ms左右。这里我们得到一个结论:

总之使用第二种遍历方法。

或者让自己的集合继承RandomAccess接口

这里我认为未实现RandomAccess接口的集合查找每个元素都是从头开始查找。而RandomAccess。可以实现快速查找集合中的元素。并且我这里只是针对在一个数量级 100w以内。数据量再大的话可以自己写个代码测试下,或者下载我的代码测试。

2-2

这里我们暂时不考虑set和map我们只关注list的集成关系。我们可以打到这样一个类图关系:



这里根据类图我们很容知道这么多继承关系就是为了实现实现和接口的分离,具体好处我也不知道,其实Abstractlist基本也没实现被子类使用,但是这样写可以为扩展提供较好的支持吧。这里仁者见仁吧。大家自己理解

这里我们一般使用的arraylist,可以知道他实现了list和Collection的接口。Arraylist其实就是一个数组的封装,我们知道数组的效率比较高,但是不能检查边界,不能对数组大小进行控制。这里我根据源码发现他仅仅是每次检查盛放数据的mArray在每次添加元素的时候都检查自己的容量。若是容量不够扩大数组大小(ps具体实现是通过native函数来的)。边界问题这里也字一直检查,具体实现我就不再详细说明(ps若是想看源码千万别再Android 提供的源码看,这写的有问题。可以直接找到Java提供的源码进行研究)

3. 后记

这里本来想好好研究的。但是忽然发现源码很简单。就没给大家详细说明。这里主要还是明白继承关系,对整体有个好的认识最好。还有关于循环。大家就可以放心的使用“`for(object o : collection){}形式了。大家放心使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: