Java集合框架 - LinkedList

首先要知道,LinkedList实现的是双向循环链表。

链表的组成元素我们称之为节点,节点由三部分组成:前一个节点的引用地址、数据、后一个节点的引用地址。LinkedList的Head节点不包含数据,每一个节点对应一个Entry对象。下面我们通过源码来分析LinkedList的实现原理。

     1、Node类源码:

复制代码
 1 private static class Node {
 2     Object item;
 3     Node next;
 4     Node prev;
 5 
 6     Node(Node Node1,Object obj, Node Node2) {
 7         item = obj;
 8         this.next = node2;
 9         this.prev = node1;
10     }
11     }
复制代码

     Node类包含三个属性,其中item存对象数据;next存放后一个节点的信息,通过next可以找到后一个节点;prev存放前一个节点的信息,通过previous可以找到前一个节点。

     2、LinkedList的构造方法:LinkedList提供了两个带不同参数的构造方法。

     1) LinkedList(),构造一个空列表。

     2) LinkedList(Collection<? extends E> c),构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。

     

复制代码
 1 private transient Node header = new Node(null, null, null); //声明一个空的Entry对象
 2 private transient int size = 0; //集合中节点的个数
 3 
 4 public LinkedList() {
 5    size = 0;  //只设置size = 0
 6 }
 7 
 8 public LinkedList(Collection<? extends E> c) {
 9    this(); //调用不带参数的构造方法,创建一个空的循环链表
10    addAll(c); //调用addAll方法将Collection的元素添加到LinkedList中
11 }
复制代码

                                                      

      当调用带集合参数的构造方法生成LinkedList对象时,会先调用不带参数的构造方法创建一个空的循环链表,然后调用addAll方法将集合元素添加到LinkedList中。
 

      3、向集合中添加元素:LinkedList提供了多种不同的add方法向集合添加元素。

      1) add(E e),将指定元素添加到此列表的结尾。

      2) add(int index, E element),在此列表中指定的位置插入指定的元素。

      3) addAll(Collection<? extends E> c),添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。

      4) addAll(int index, Collection<? extends E> c),将指定 collection 中的所有元素从指定位置开始插入此列表。

      5) addFirst(E e),将指定元素插入此列表的开头。

      6) addLast(E e),将指定元素添加到此列表的结尾。 

      通过源码来分析其底层的实现原理:  

      

复制代码
 1 public boolean add(Object obj) {
 2     linkLast(obj);  
 3     return true;
 4 }
 5 private void linkFirst(Object obj)
    {
        Node node1 = first;
        Node node2 = new Node(null, obj, node1);
        first = node2;
        if(node1 == null)
            last = node2;
        else
            node1.prev = node2;
        size++;
        modCount++;
    }


   void linkLast(Object obj)
    {
        Node node1 = last;	//初始化的时候last为null
        Node node2 = new Node(node1, obj, null);    //刚开始的时候直接添加obj
        last = node2;   //把第一个放进来的存obj的Node设为last 
        if(node1 == null)
            first = node2;	//把第一个Node设为first
        else
            node1.next = node2;
        size++;
        modCount++;
    }
复制代码

     这个过程很简单,基本的数据结构

    add 另一个方法和addAll()方法

1 public void add(int i, Object obj) {
2       checkPositionIndex(i);
        if(i == size)
            linkLast(obj);
        else
            linkBefore(obj, node(i));
3 }
//判断是否index越界也就是size小于i
 private void checkPositionIndex(int i)
    {
        if(!isPositionIndex(i))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(i));
        else
            return;
    }
private boolean isPositionIndex(int i)
    {
        return i >= 0 && i <= size;
    }
//查找要插入的Node节点
 Node node(int i)
    {
        if(i < size >> 1)
        {
            Node node1 = first;
            for(int j = 0; j < i; j++)
                node1 = node1.next;
            return node1;
        }
        Node node2 = last;
        for(int k = size - 1; k > i; k--)
            node2 = node2.prev;
        return node2;
    }
//在Node1之前插入
void linkBefore(Object obj, Node node1)
    {
        Node node2 = node1.prev;
        Node node3 = new Node(node2, obj, node1);  //创建一个Node3 前驱为Node2,后为Node1
        node1.prev = node3;
        if(node2 == null)
            first = node3;
        else
            node2.next = node3;
        size++;
        modCount++;
    }
复制代码
 1 public boolean addAll(Collection<? extends E> c) {
 2         return addAll(size, c);
 3 }
 4 
 5 public boolean addAll(int index, Collection<? extends E> c) {
 6         checkPositionIndex(i);
 9         Object aobj[] = collection.toArray();
        int j = aobj.length;
        if(j == 0)
            return false;
        Node node1;  //保存前驱和后继节点
        Node node2;
	//判断是在尾部还是中间和前面插入 个人觉得有点多余  因为是在size后面添加
        if(i == size)
        {
            node2 = null;
            node1 = last;
        } else
        {
            node2 = node(i);
            node1 = node2.prev;
        }
        Object aobj1[] = aobj;
        int k = aobj1.length;
        for(int l = 0; l < k; l++)
        {
            Object obj = aobj1[l];
            Object obj1 = obj;
            Node node3 = new Node(node1, obj1, null);
            if(node1 == null)
                first = node3;
            else
                node1.next = node3;
            node1 = node3;
        }

        if(node2 == null)
        {
            last = node1;
        } else
        {
            node1.next = node2;
            node2.prev = node1;
        }
        size += j;
        modCount++;
        return true;
26     }
复制代码

     4、获取LinkedList中的元素:

    get方法更简单,先检查是否越界,然后直接Node(int i).Item就可以得到了。

     5、移除LinkedList中的元素:

     1) remove(int index),移除此列表中指定位置处的元素。

     2) remove(Object o),从此列表中移除首次出现的指定元素(如果存在)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值