对LinkedList的理解

LinkedList是Collection的一个list实现。与ArrayList的区别是LinkedList是一个链表结构,ArrayList是一个顺序结构。LinkedList和ArrayList的比较:

  1. 顺序插入速度ArrayList会比较快,因为ArrayList是基于数组实现的,数组是事先new好的,只要往指定的位置加入一个数据就好了;LinkedList每次顺序插入的时候先new一个对象出来,如果对象比较大,那么new的时间会长一点,还有引用赋值的操作,这些决定了顺序插入LinkedList比ArrayList慢
  2. ArrayList的遍历效率比LinkedList的效率高
  3. LinkedList做插入删除的时候,慢在寻址,快在只需要改变前后的Node的引用地址;ArrayList做插入删除的时候,慢在数组元素的批量copy,快在寻址
  4. 如果确定插入删除元素在前半段,用LinkedList;如果在比较靠后的位置,那就考虑使用ArrayList;如果不确定,那就用LinkedList
  5. LinkedList整体插入、删除的执行效率比较稳定,ArrayList是越往后越快的情况;插入元素的时候,ArrayList可能要进行一次扩容,而ArrayList底层数组扩容是一个既消耗时间又消耗空间的操作

概述:

  1. LinkedList是双向链表实现的List。
  2. LinkedList是非线程安全的
  3. LinkedList元素允许为null,允许重复元素
  4. LinkedList是基于链表实现的,因此插入删除效率高,查找效率低;因此不存在容量不足的问题,所以没有扩容方法。千万不要通过随机访问去遍历LinkedList。
  5. LinkedList还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用
  6. LinkedList实现了List接口,所以能对它进行队列操作;实现了Deque接口,能将LinkedList当作双端队列使用;实现了Cloneable接口,即覆盖了函数clone()可以克隆;实现了java.io.Serializable接口,所以LinkedList支持序列化,能通过序列化去传输
  7. LinkedList包含两个重要的成员:headersize。header是双向链表的表头,它是双向链表节点所对相应的类Entry的的实例。Entry中包含成员变量:previous,next,element。其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。size是双向链表中节点的个数。

LinkedList的数据结构

LinkedList的继承关系

java.lang.Object
   ↳     java.util.AbstractCollection<E>
         ↳     java.util.AbstractList<E>
               ↳     java.util.AbstractSequentialList<E>
                     ↳     java.util.LinkedList<E>

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {}

在这里插入图片描述

1public LinkedList()//默认构造函数,生成空链表
2public LinkedList(Collection<? extends E> collection)
//创建一个LinkedList,保护Collection中的全部元素

获取链表的第一个和最后一个元素

import java.util.LinkedList;  
  
public class LinkedListTest{  
  public static void main(String[] args) {  
    LinkedList<String> list=new LinkedList<String>();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    
    System.out.println("链表的第一个元素是 : " + list.getFirst());//1  
    System.out.println("链表最后一个元素是 : " + list.getLast());  //4
  }  
}  

获取链表元素

for(String str:list){
	System.out.println(str);
}

从链表生成子表

List sub=list.subList(1,4);
	System.out.println(sub);
	lst.remove(2);  
    System.out.println(lst);  
    System.out.println(list);

添加元素:添加单个元素
如果不指定索引的话,元素将被添加到链表的最后.

public boolean add(Object element)
public boolean add(int index, Object element)

也可以把链表当初栈或者队列来处理:

public boolean addFirst(Object element)
public boolean addLast(Object element)

addLast()方法和不带索引的add()方法实现的效果一样.

public class LinkedListTest{  
  public static void main(String[] a) {  
    LinkedList list = new LinkedList();  
    list.add("A");  
    list.add("B");  
    list.add("C");  
    list.add("D");  
    list.addFirst("X");  
    list.addLast("Z");  
    System.out.println(list);  
  }  
}  

删除元素

public Object removeFirst()  
public Object removeLast()  
import java.util.LinkedList;  
  
  
public class MainClass {  
  public static void main(String[] a) {  
  
  
    LinkedList list = new LinkedList();  
    list.add("A");  
    list.add("B");  
    list.add("C");  
    list.add("D");  
    list.removeFirst();  
    list.removeLast();  
    System.out.println(list);  
  }  
}  

使用链表实现栈效果

import java.util.LinkedList;  
public class MainClass {  
  public static void main(String[] args) {  
    StackL stack = new StackL();  
    for (int i = 0; i < 10; i++)  
      stack.push(i);  
    System.out.println(stack.top());  
    System.out.println(stack.top());  
    System.out.println(stack.pop());  
    System.out.println(stack.pop());  
    System.out.println(stack.pop());  
  }  
}  
class StackL {  
  private LinkedList list = new LinkedList();  
  public void push(Object v) {  
    list.addFirst(v);  
  }  
  public Object top() {  
    return list.getFirst();  
  }  
  public Object pop() {  
    return list.removeFirst();  
  }  
}  

使用链表实现队列效果

import java.util.LinkedList;  
public class MainClass {  
  public static void main(String[] args) {  
    Queue queue = new Queue();  
    for (int i = 0; i < 10; i++)  
      queue.put(Integer.toString(i));  
    while (!queue.isEmpty())  
      System.out.println(queue.get());  
  }  
}  
class Queue {  
  private LinkedList list = new LinkedList();  
  public void put(Object v) {  
    list.addFirst(v);  
  }  
  public Object get() {  
    return list.removeLast();  
  }  
  public boolean isEmpty() {  
    return list.isEmpty();  
  }  
}  

将LinkedList转换成ArrayList

ArrayList<String> arrayList = new ArrayList<String>(linkedList);  
    for (String s : arrayList) {  
      System.out.println("s = " + s);  
    }  

删除列表的首位元素

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    System.out.println(lList);  
        //元素在删除的时候,仍然可以获取到元素  
    Object object = lList.removeFirst();  
    System.out.println(object + " has been removed");  
    System.out.println(lList);  
    object = lList.removeLast();  
    System.out.println(object + " has been removed");  
    System.out.println(lList);  
  }  
}  

根据范围删除列表元素

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    System.out.println(lList);  
    lList.subList(2, 5).clear();  
    System.out.println(lList);  
  }  
}  

删除链表的特定元素

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    System.out.println(lList);  
    System.out.println(lList.remove("2"));//删除元素值=2的元素  
    System.out.println(lList);  
    Object obj = lList.remove(2);  //删除第二个元素  
    System.out.println(obj + " 已经从链表删除");  
    System.out.println(lList);  
  }  
}  

将LinkedList转换为数组,数组长度为0

import java.util.LinkedList;  
import java.util.List;  
public class Main {  
  public static void main(String[] args) {  
    List<String> theList = new LinkedList<String>();  
    theList.add("A");  
    theList.add("B");  
    theList.add("C");  
    theList.add("D");  
    String[] my = theList.toArray(new String[0]);  
    for (int i = 0; i < my.length; i++) {  
      System.out.println(my[i]);  
    }  
  }  
}  

将LinkedList转换为数组,数组长度为链表长度

import java.util.LinkedList;  
import java.util.List;  
public class Main {  
  public static void main(String[] args) {  
    List<String> theList = new LinkedList<String>();  
    theList.add("A");  
    theList.add("B");  
    theList.add("C");  
    theList.add("D");  
    String[] my = theList.toArray(new String[theList.size()]);  
    for (int i = 0; i < my.length; i++) {  
      System.out.println(my[i]);  
    }  
  }  
}  

将LinkedList转换成ArrayList

import java.util.ArrayList;  
import java.util.LinkedList;  
import java.util.List;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> myQueue = new LinkedList<String>();  
    myQueue.add("A");  
    myQueue.add("B");  
    myQueue.add("C");  
    myQueue.add("D");  
    List<String> myList = new ArrayList<String>(myQueue);  
    for (Object theFruit : myList)  
      System.out.println(theFruit);  
  }  
}  

实现栈

import java.util.Collections;  
import java.util.LinkedList;  
public class Main {  
  public static void main(String[] argv) throws Exception {  
    LinkedList stack = new LinkedList();  
    Object object = "";  
    stack.addFirst(object);  
    Object o = stack.getFirst();  
    stack = (LinkedList) Collections.synchronizedList(stack);  
  }  
}  

实现队列

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] argv) throws Exception {  
    LinkedList queue = new LinkedList();  
    Object object = "";  
    // Add to end of queue  
    queue.add(object);  
    // Get head of queue  
    Object o = queue.removeFirst();  
  }  
}  

同步方法

import java.util.Collections;  
import java.util.LinkedList;  
public class Main {  
  public static void main(String[] argv) throws Exception {  
    LinkedList queue = new LinkedList();  
    Object object = "";  
    queue.add(object);  
    Object o = queue.removeFirst();  
    queue = (LinkedList) Collections.synchronizedList(queue);  
  }  
}  

查找元素位置

import java.util.LinkedList;  
  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    lList.add("2");  
    System.out.println(lList.indexOf("2"));  
    System.out.println(lList.lastIndexOf("2"));  
  }  
}  

替换元素

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    System.out.println(lList);  
    lList.set(3, "Replaced");//使用set方法替换元素,方法的第一个参数是元素索引,后一个是替换值  
    System.out.println(lList);  
  }  
}  

链表添加对象

import java.util.LinkedList;  
class Address {  
  private String name;  
  private String street;  
  private String city;  
  private String state;  
  private String code;  
  Address(String n, String s, String c, String st, String cd) {  
    name = n;  
    street = s;  
    city = c;  
    state = st;  
    code = cd;  
  }  
  public String toString() {  
    return name + " " + street + " " + city + " " + state + " " + code;  
  }  
}  

class MailList {  
  public static void main(String args[]) {  
    LinkedList<Address> ml = new LinkedList<Address>();  
    ml.add(new Address("A", "11 Ave", "U", "IL", "11111"));  
    ml.add(new Address("R", "11 Lane", "M", "IL", "22222"));  
    ml.add(new Address("T", "8 St", "C", "IL", "33333"));  
    for (Address element : ml)  
      System.out.println(element + "\n");  
  }  
}  

确认链表是否存在特定元素

import java.util.LinkedList;  
public class Main {  
  public static void main(String[] args) {  
    LinkedList<String> lList = new LinkedList<String>();  
    lList.add("1");  
    lList.add("2");  
    lList.add("3");  
    lList.add("4");  
    lList.add("5");  
    if (lList.contains("4")) {  
      System.out.println("LinkedList contains 4");  
    } else {  
      System.out.println("LinkedList does not contain 4");  
    }  
  }  
}  

根据链表元素生成对象数组

Object[] objArray = lList.toArray();  
for (Object obj: objArray) {  
   System.out.println(obj);  
}  

链表多线程

import java.util.Collections;  
import java.util.LinkedList;  
import java.util.List;  
class PrepareProduction implements Runnable {  
  private final List<String> queue;  
  PrepareProduction(List<String> q) {  
    queue = q;  
  }  
  public void run() {  
    queue.add("1");  
    queue.add("done");  
  }  
}  
class DoProduction implements Runnable {  
  private final List<String> queue;  
  DoProduction(List<String> q) {  
    queue = q;  
  }  
  public void run() {  
    String value = queue.remove(0);  
    while (!value.equals("*")) {  
      System.out.println(value);  
      value = queue.remove(0);  
    }  
  }  
}  
public class Main {  
  public static void main(String[] args) throws Exception {  
    List q = Collections.synchronizedList(new LinkedList<String>());  
    Thread p1 = new Thread(new PrepareProduction(q));  
    Thread c1 = new Thread(new DoProduction(q));  
    p1.start();  
    c1.start();  
    p1.join();  
    c1.join();  
  }  
}  

优先级链表(来自JBOSS)

import java.util.ArrayList;  
import java.util.LinkedList;  
import java.util.List;  
import java.util.ListIterator;  
import java.util.NoSuchElementException;  
  
public class BasicPriorityLinkedList {  
  
  protected LinkedList[] linkedLists;  
  protected int priorities;  
  protected int size;  
  
  public BasicPriorityLinkedList(int priorities) {  
    this.priorities = priorities;  
    initDeques();  
  }  
  public void addFirst(Object obj, int priority) {  
    linkedLists[priority].addFirst(obj);  
    size++;  
  }  
  public void addLast(Object obj, int priority) {  
    linkedLists[priority].addLast(obj);  
    size++;  
  }  
  public Object removeFirst() {  
    Object obj = null;  
    for (int i = priorities - 1; i >= 0; i--) {  
      LinkedList ll = linkedLists[i];  
      if (!ll.isEmpty()) {  
        obj = ll.removeFirst();  
        break;  
      }  
    }  
    if (obj != null) {  
      size--;  
    }  
    return obj;  
  }  
  public Object removeLast() {  
    Object obj = null;  
    for (int i = 0; i < priorities; i++) {  
      LinkedList ll = linkedLists[i];  
      if (!ll.isEmpty()) {  
        obj = ll.removeLast();  
      }  
      if (obj != null) {  
        break;  
      }  
    }  
    if (obj != null) {  
      size--;  
    }  
    return obj;  
  }  
  
  
  public Object peekFirst() {  
    Object obj = null;  
    for (int i = priorities - 1; i >= 0; i--) {  
      LinkedList ll = linkedLists[i];  
      if (!ll.isEmpty()) {  
        obj = ll.getFirst();  
      }  
      if (obj != null) {  
        break;  
      }  
    }  
    return obj;  
  }  
  
  public List getAll() {  
    List all = new ArrayList();  
    for (int i = priorities - 1; i >= 0; i--) {  
      LinkedList deque = linkedLists[i];  
      all.addAll(deque);  
    }  
    return all;  
  }  
  
  public void clear() {  
    initDeques();  
  }  
  
  public int size() {  
    return size;  
  }  
  
  public boolean isEmpty() {  
    return size == 0;  
  }  
  
  public ListIterator iterator() {  
    return new PriorityLinkedListIterator(linkedLists);  
  }  
  
  protected void initDeques() {  
    linkedLists = new LinkedList[priorities];  
    for (int i = 0; i < priorities; i++) {  
      linkedLists[i] = new LinkedList();  
    }  
    size = 0;  
  }  
  
  class PriorityLinkedListIterator implements ListIterator {  
    private LinkedList[] lists;  
    private int index;  
    private ListIterator currentIter;  
    PriorityLinkedListIterator(LinkedList[] lists) {  
      this.lists = lists;  
      index = lists.length - 1;  
      currentIter = lists[index].listIterator();  
    }  
  
    public void add(Object arg0) {  
      throw new UnsupportedOperationException();  
    }  
  
    public boolean hasNext() {  
      if (currentIter.hasNext()) {  
        return true;  
      }  
      while (index >= 0) {  
        if (index == 0 || currentIter.hasNext()) {  
          break;  
        }  
        index--;  
        currentIter = lists[index].listIterator();  
      }  
      return currentIter.hasNext();  
    }  
  
    public boolean hasPrevious() {  
      throw new UnsupportedOperationException();  
    }  
  
    public Object next() {  
      if (!hasNext()) {  
        throw new NoSuchElementException();  
      }  
      return currentIter.next();  
    }  
  
    public int nextIndex() {  
      throw new UnsupportedOperationException();  
    }  
  
    public Object previous() {  
      throw new UnsupportedOperationException();  
    }  
  
    public int previousIndex() {  
      throw new UnsupportedOperationException();  
    }  
  
    public void remove() {  
      currentIter.remove();  
      size--;  
    }  
  
    public void set(Object obj) {  
      throw new UnsupportedOperationException();  
    }  
  }  
}  

生成list的帮助类(来自google)

import java.util.ArrayList;  
import java.util.Collections;  
import java.util.LinkedList;  
import java.util.List;  
public class Lists {  
  private Lists() { }  
  public static <E> ArrayList<E> newArrayList() {  
    return new ArrayList<E>();  
  }  
  public static <E> ArrayList<E> newArrayListWithCapacity(int initialCapacity) {  
    return new ArrayList<E>(initialCapacity);  
  }  
  public static <E> ArrayList<E> newArrayList(E... elements) {  
    ArrayList<E> set = newArrayList();  
    Collections.addAll(set, elements);  
    return set;  
  }  
  public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {  
    ArrayList<E> list = newArrayList();  
    for(E e : elements) {  
      list.add(e);  
    }  
    return list;  
  }  
  public static <E> LinkedList<E> newLinkedList() {  
    return new LinkedList<E>();  
  }  
}  

常用的API操作

import java.util.List;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;

public class LinkedListTest {
    public static void main(String[] args) {
        // 测试LinkedList的API
        testLinkedListAPIs() ;

        // 将LinkedList当作 LIFO(后进先出)的堆栈
        useLinkedListAsLIFO();

        // 将LinkedList当作 FIFO(先进先出)的队列
        useLinkedListAsFIFO();
    }

    /*
     * 测试LinkedList中部分API
     */
    private static void testLinkedListAPIs() {
        String val = null;
        //LinkedList llist;
        //llist.offer("10");
        // 新建一个LinkedList
        LinkedList llist = new LinkedList();
        //---- 添加操作 ----
        // 依次添加1,2,3
        llist.add("1");
        llist.add("2");
        llist.add("3");

        // 将“4”添加到第一个位置
        llist.add(1, "4");


        System.out.println("\nTest \"addFirst(), removeFirst(), getFirst()\"");
        // (01) 将“10”添加到第一个位置。  失败的话,抛出异常!
        llist.addFirst("10");
        System.out.println("llist:"+llist);
        // (02) 将第一个元素删除。        失败的话,抛出异常!
        System.out.println("llist.removeFirst():"+llist.removeFirst());
        System.out.println("llist:"+llist);
        // (03) 获取第一个元素。          失败的话,抛出异常!
        System.out.println("llist.getFirst():"+llist.getFirst());


        System.out.println("\nTest \"offerFirst(), pollFirst(), peekFirst()\"");
        // (01) 将“10”添加到第一个位置。  返回true。
        llist.offerFirst("10");
        System.out.println("llist:"+llist);
        // (02) 将第一个元素删除。        失败的话,返回null。
        System.out.println("llist.pollFirst():"+llist.pollFirst());
        System.out.println("llist:"+llist);
        // (03) 获取第一个元素。          失败的话,返回null。
        System.out.println("llist.peekFirst():"+llist.peekFirst());


        System.out.println("\nTest \"addLast(), removeLast(), getLast()\"");
        // (01) 将“20”添加到最后一个位置。  失败的话,抛出异常!
        llist.addLast("20");
        System.out.println("llist:"+llist);
        // (02) 将最后一个元素删除。        失败的话,抛出异常!
        System.out.println("llist.removeLast():"+llist.removeLast());
        System.out.println("llist:"+llist);
        // (03) 获取最后一个元素。          失败的话,抛出异常!
        System.out.println("llist.getLast():"+llist.getLast());


        System.out.println("\nTest \"offerLast(), pollLast(), peekLast()\"");
        // (01) 将“20”添加到第一个位置。  返回true。
        llist.offerLast("20");
        System.out.println("llist:"+llist);
        // (02) 将第一个元素删除。        失败的话,返回null。
        System.out.println("llist.pollLast():"+llist.pollLast());
        System.out.println("llist:"+llist);
        // (03) 获取第一个元素。          失败的话,返回null。
        System.out.println("llist.peekLast():"+llist.peekLast());



        // 将第3个元素设置300。不建议在LinkedList中使用此操作,因为效率低!
        llist.set(2, "300");
        // 获取第3个元素。不建议在LinkedList中使用此操作,因为效率低!
        System.out.println("\nget(3):"+llist.get(2));


        // ---- toArray(T[] a) ----
        // 将LinkedList转行为数组
        String[] arr = (String[])llist.toArray(new String[0]);
        for (String str:arr)
            System.out.println("str:"+str);

        // 输出大小
        System.out.println("size:"+llist.size());
        // 清空LinkedList
        llist.clear();
        // 判断LinkedList是否为空
        System.out.println("isEmpty():"+llist.isEmpty()+"\n");

    }

    /**
     * 将LinkedList当作 LIFO(后进先出)的堆栈
     */
    private static void useLinkedListAsLIFO() {
        System.out.println("\nuseLinkedListAsLIFO");
        // 新建一个LinkedList
        LinkedList stack = new LinkedList();

        // 将1,2,3,4添加到堆栈中
        stack.push("1");
        stack.push("2");
        stack.push("3");
        stack.push("4");
        // 打印“栈”
        System.out.println("stack:"+stack);

        // 删除“栈顶元素”
        System.out.println("stack.pop():"+stack.pop());

        // 取出“栈顶元素”
        System.out.println("stack.peek():"+stack.peek());

        // 打印“栈”
        System.out.println("stack:"+stack);
    }

    /**
     * 将LinkedList当作 FIFO(先进先出)的队列
     */
    private static void useLinkedListAsFIFO() {
        System.out.println("\nuseLinkedListAsFIFO");
        // 新建一个LinkedList
        LinkedList queue = new LinkedList();

        // 将10,20,30,40添加到队列。每次都是插入到末尾
        queue.add("10");
        queue.add("20");
        queue.add("30");
        queue.add("40");
        // 打印“队列”
        System.out.println("queue:"+queue);

        // 删除(队列的第一个元素)
        System.out.println("queue.remove():"+queue.remove());

        // 读取(队列的第一个元素)
        System.out.println("queue.element():"+queue.element());

        // 打印“队列”
        System.out.println("queue:"+queue);
    }
}

运行结果:

Test "addFirst(), removeFirst(), getFirst()"
llist:[10, 1, 4, 2, 3]
llist.removeFirst():10
llist:[1, 4, 2, 3]
llist.getFirst():1

Test "offerFirst(), pollFirst(), peekFirst()"
llist:[10, 1, 4, 2, 3]
llist.pollFirst():10
llist:[1, 4, 2, 3]
llist.peekFirst():1

Test "addLast(), removeLast(), getLast()"
llist:[1, 4, 2, 3, 20]
llist.removeLast():20
llist:[1, 4, 2, 3]
llist.getLast():3

Test "offerLast(), pollLast(), peekLast()"
llist:[1, 4, 2, 3, 20]
llist.pollLast():20
llist:[1, 4, 2, 3]
llist.peekLast():3

get(3):300
str:1
str:4
str:300
str:3
size:4
isEmpty():true


useLinkedListAsLIFO
stack:[4, 3, 2, 1]
stack.pop():4
stack.peek():3
stack:[3, 2, 1]

useLinkedListAsFIFO
queue:[10, 20, 30, 40]
queue.remove():10
queue.element():20
queue:[20, 30, 40]

LinkedList方法
参考文章

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页