学习ArrayList和LinkedList
ArrayList其实本质上就是一个数组,它无可避免的存在数组的特质:get()和set()方法效率很高,花费常数时间,而插入和删除操作的代价昂贵(除非是从数组末尾进行删除)。
而LinkedList使用的是双向链表,对于插入和删除花费的是常数时间,而对于get()方法则代价昂贵。
《数据结构与算法分析-java语言描述》这本书上面有几个示例代码很有趣:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* 理解ArrayList和LinkedList本质,从而选择高效的数据结构
* <p>Title: TestLinkedList1</p>
* <p>Description: </p>
* <p>Company: www.itcast.cn</p>
* @version 1.0
*/
public class TestLinkedList1 {
//从List末尾添加元素
public static void makeList1(List<Integer> l,int N){
for (int i = 0; i < N; i++) {
l.add(i);
}
}
//从List头添加元素
public static void makeList2(List<Integer> l,int N){
for (int i = 0; i < N; i++) {
l.add(0,i);
}
}
//删除List中的偶数元素
public static void removeFromList(List<Integer> l){
//ArrayList有一个iterator()方法,返回一个Itr对象(Itr为ArrayList内部类,其实现了Iterator接口),该对象包含三个方法:hashNext(),next(),remove()
Iterator<Integer> iterator = l.iterator();
while(iterator.hasNext()){
if (iterator.next() % 2 == 0) {
iterator.remove();
}
}
}
public static void main(String[] args) {
List<Integer> l1 = new ArrayList<>();
List<Integer> l2 = new LinkedList<>();
//计算添加元素操作使用时间
long startTime=System.currentTimeMillis(); //获取开始时间
//makeList1(l1, 100000);//耗时9ms
//makeList1(l2, 100000);//耗时10ms
//makeList2(l1, 100000);//耗时943ms
makeList2(l1, 100000);//耗时14ms
removeFromList(l1);//761ms
//removeFromList(l2);//10ms
}
}
通过上面的代码运行时间可以发现:
1.向List尾部添加元素,ArrayList和LinkedList耗时是一样的
2.向List头部添加元素,ArrayList要比LinkedList耗时多很多,是因为向ArrayList头部添加元素时间复杂度是O(N2)
3.删除List中的元素,同样是ArrayList要比LinkedList耗时很多。因为每次remove操作,数组都需要移动。
一点说明:
通过扒源码发现,ArrayList的iterator()方法和LinkedList的iterator()方法得到返回值不一样,前者得到的是一个Itr对象(Itr为ArrayList内部类,它实现了Iterator接口),该对象包含三个方法:hashNext(),next(),remove()。
而LinkedList的iterator方法并不是在其内部实现的,而是通过继承抽象类AbstractSequentialList,AbstractSequentialList实现了iterator()方法,返回时调用 listIterator()方法,而listIterator()在抽象类AbstractList<E>中返回一个ListIterator<E>接口对象,该接口包含了如下的方法:
显然比Iterator接口多了好几个方法。