Java 集合里面最重要的List接口,准备仔细的分析一下List。
一. List接口
1. List 首先它的数据结构就是一个序列,存储内容时直接在内存中开辟一块连续的空间,然后将空间地址和索引对应。在插入元素时,会根据索引进行排序。
2. 继承 Collection,实现了Collection的所有方法,是一个元素有序的,可以重复的,元素可以为null的集合。
3. List最经常使用的ArrayList,LinkedList和Vector。
4. 默认List 和数组一样,都是从0开始,根据元素在list中的位置,实现元素的get、set、add、addAll、remove等操作;
二. List的操作:
remove(Object)删除元素的指定操作,set方法则是覆盖。
add(E)添加元素到list的尾部,
addAll(Collection<? extends E)添加集合到list尾部。
indexOf、lastIndexOf返回指定元素在list的位置,获取lastIndexOf是通过倒序遍历查找。
list进行比较则需要重写equals()和hashcode()方法进行比较,equals和==方法则只是比较地址是否相等。
subList(int fromIndex,int tolndex)方法返回的是在这个范围的子集,左闭右开。这个方法只是持有原来数组的引用,并不是创建一个新的list数组。
三 .针对List数组遍历方法:
(1)普通循环遍历:效率最高
private void test1(List<Integer> list) {
long before = System.currentTimeMillis();
int j = list.size();
for (int i = 0; i < j; i++) {
}
long after = System.currentTimeMillis();
Log.e("TAG", "test1: "+(after - before));
}
(2)迭代器Iterator操作:其底层代码通过Iterator绕了一道再操作底层数组,所以速度稍慢。需要注意的是Iterator对象的remove方法是迭代过程中删除元素的唯一方法 。可能会产生fail-east事件
example:
private void test2(List<Integer> list) {
long before = System.currentTimeMillis();
for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
iterator.next();
}
long after = System.currentTimeMillis();
Log.e("TAG", "test2: "+(after - before));
}
(3)增强for循环:内部实际上是用迭代器来实现的。
public static void test3(List<Integer> list) {
long before = System.currentTimeMillis();
for (int i : list) {
}
long after = System.currentTimeMillis();
System.out.println(after - before);
Log.e("TAG", "test3: "+(after - before));
}
(4)for earch 方法(Java8的新方法):
实际上也是增强for循环,for-each 循环只是标准 Iterator 代码标准用法之上的一种语法糖(syntactic sugar)。
private void test4(List<Integer> list) {
long before = System.currentTimeMillis();
list.forEach(item -> {
});
long after = System.currentTimeMillis();
System.out.println(after - before);
Log.e("TAG", "test4: "+(after - before));
}
(5)stream方法,Java8 stream流处理新方法,速度跟4差不多,
private void test5(List<Integer> list) {
long before = System.currentTimeMillis();
list.stream().forEach(item -> {
});
long after = System.currentTimeMillis();
System.out.println(after - before);
Log.e("TAG", "test5: "+(after - before));
}
区别: for 、forEarch、Iterator:
(1)for循环:必须知道集合和数组的大小,而且是有序的,实现了RandomAccess随机访问接口,因此它对随机访问的速度快。
forearch、iterator:不需要知道集合或者数组得大小,他们是得到集合内的每个元素然后进行处理。
(2)for、forearch:都需要知道集合的类型,需要访问内部的成员。
iterator:是一个接口类型,不关心集合或者数组的类型,能随时修改和删除元素。
四 .效率问题:
基本的for循环的效率一定比iterator迭代器的高?
不一定主要看集合的数据结构组成。ArrayList和LinkedList就不同。
ArrayList实现了RandomAccess随机访问接口。所以其get()访问取元素的速度最快。
LinkedList采取的是顺序访问方式,iterator的next()方法采用的就是顺序访问方法,所以在LinkedList里面使用iterator速度较快。