参考的博客
Java 集合系列05之 LinkedList详细介绍(源码解析)和使用示例
如果你想详细的区了解容器知识以及本文讲的LinkedList,我推荐你去看这篇博客和这个做个的容器系列
LinkedList
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
LinkedList是基于双向链表的,它继承了AbstractSequentialList类,实现了List等接口,它与ArrayList最大的区别就是他们基于的数据结构是不一样的,ArrayList是数组。因此当你随机访问(通过get(i这种操作),LinkedList效率是很低的,它的get方法本质一次次遍历index,不停的自加找到位置,所以非常慢。我测试了遍历,可以看下常用的三种遍历方式的耗时
LinkedList作为队列
队列的特点就是先进先出。
我下面的例子实际上用了add方法添加元素,add方法调用的是addLast方法,这样后加的元素就在最后啦,遍历的又调用pee方法,peek方法如下
public E peek() {
final Node<E> f = first;
return (f == null) ? null : f.item;
}
每次读的就是第一个,这样就先进先出了_。
LinkedList作为栈
栈的特点就是后进先出
我下面的例子,在存的是用的push方法,push调用是addFirst,因此最后加的就成为第一元素了。
遍历的时候调用element,它的实现是getFirst方法
public E element() {
return getFirst();
}
最后进的放在第一位,然后你再去get第一位,模拟出栈的操作。
代码测试
package com.fang.java.javabase.firstcollection;
import java.util.Iterator;
import java.util.LinkedList;
import lombok.extern.slf4j.Slf4j;
@Slf4j
/*
LinkedList的API
boolean add(E object)
void add(int location, E object)
boolean addAll(Collection<? extends E> collection)
boolean addAll(int location, Collection<? extends E> collection)
void addFirst(E object)
void addLast(E object)
void clear()
Object clone()
boolean contains(Object object)
Iterator<E> descendingIterator()
E element()
E get(int location)
E getFirst()
E getLast()
int indexOf(Object object)
int lastIndexOf(Object object)
ListIterator<E> listIterator(int location)
boolean offer(E o)
boolean offerFirst(E e)
boolean offerLast(E e)
E peek()
E peekFirst()
E peekLast()
E poll()
E pollFirst()
E pollLast()
E pop()
void push(E e)
E remove()
E remove(int location)
boolean remove(Object object)
E removeFirst()
boolean removeFirstOccurrence(Object o)
E removeLast()
boolean removeLastOccurrence(Object o)
E set(int location, E object)
int size()
<T> T[] toArray(T[] contents)
Object[] toArray()
*/
public class LinkedListTest{
public static void main(String[] args) {
//测试遍历
iteratorLinkedlist(getList());
forLinkedlist(getList());
forEachLinkedlist(getList());
//测试API
testLinkedListPartAPIs();
//测试栈
useLinkedListAsLIFO();
//测试队列
useLinkedListAsFIFO();
}
private static LinkedList getList(){
LinkedList list=new LinkedList<>();
for(int i=0 ;i<50000;i++){
list.add(i);
}
return list;
}
//itetator
private static void iteratorLinkedlist(LinkedList<Integer> list){
long start=System.currentTimeMillis();
Iterator it=list.iterator();
while(it.hasNext()){
it.next();
}
long end=System.currentTimeMillis();
log.info("iterator Linkedlist: "+(end-start)+"ms");
}
//for
private static void forLinkedlist(LinkedList<Integer> list){
long start=System.currentTimeMillis();
for(int i=0;i<list.size();i++){
list.get(i);
}
long end=System.currentTimeMillis();
log.info("for Linkedlist: "+(end-start)+"ms");
}
//foreach
private static void forEachLinkedlist(LinkedList<Integer> list){
long start=System.currentTimeMillis();
for(Integer i:list){
}
long end=System.currentTimeMillis();
log.info("forEach Linkedlist: "+(end-start)+"ms");
}
private static void testLinkedListPartAPIs(){
LinkedList <String>list =new LinkedList<String>();
log.info("test API");
list.add("10");
list.add("20");
list.add("30");
//add first
list.addFirst("first");
//get first
log.info("Test get First {}",list.getFirst());
//add last
list.addLast("last");
//get last
log.info("Test get Last {}", list.getLast());
}
/*
模拟
将LinkedList当作 LIFO(后进先出)的堆栈
*/
private static void useLinkedListAsLIFO(){
LinkedList<String> stack=new LinkedList<>();
//push(E e) 将元素推入此列表所表示的堆栈。是靠着addFirst(e)实现;
stack.push("1");
stack.push("2");
stack.push("3");
stack.push("4");
log.info("test LinkedList");
log.info(stack.toString());//[4, 3, 2, 1]
//peek() 获取但不移除此列表的头(第一个元素)。遍历第一个
//pop() 从此列表所表示的堆栈处弹出一个元素。removeFirst
log.info(stack.pop());
log.info(stack.peek());
}
/*
将LinkedList当作 FIFO(先进先出)的队列
*/
private static void useLinkedListAsFIFO() {
LinkedList<String> queue=new LinkedList<>();
queue.add("1");
queue.add("2");
queue.add("3");
queue.add("4");
log.info("test LinkedList queue");
log.info(queue.toString());
//remove() 获取并移除此列表的头(第一个元素
log.info(queue.remove());
//element()获取但不移除此列表的头(第一个元素)。
log.info(queue.element());
}
}
测试结果
2019-07-05 11:38:46,958 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - iterator Linkedlist: 5ms
2019-07-05 11:38:48,322 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - for Linkedlist: 1359ms
2019-07-05 11:38:48,330 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - forEach Linkedlist: 3ms
2019-07-05 11:38:48,330 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - test API
2019-07-05 11:38:48,335 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - Test get First first
2019-07-05 11:38:48,335 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - Test get Last last
2019-07-05 11:38:48,336 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - test LinkedList stack
2019-07-05 11:38:48,336 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - [4, 3, 2, 1]
2019-07-05 11:38:48,336 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - 4
2019-07-05 11:38:48,337 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - 3
2019-07-05 11:38:48,337 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - test LinkedList queue
2019-07-05 11:38:48,337 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - [1, 2, 3, 4]
2019-07-05 11:38:48,337 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - 1
2019-07-05 11:38:48,337 [main] INFO com.fang.java.javabase.firstcollection.LinkedListTest - 2