ArrayList与LinkedList

ArrayList
ArrayList是一个其容量能够动态增长的动态数组。它继承了AbstractList,实现了List、RandomAccess, Cloneable, java.io.Serializable。
基本的ArrayList,长于随机访问元素,但是在List中间插入和移除元素时较慢。

ArrayList有三种遍历方式
分别是索引值遍历,迭代器遍历还有for循环遍历
遍历ArrayList时,通过索引值遍历效率最高,for循环遍历次之,迭代器遍历最低。

ArrayList源码解析

类成员

    // 序列版本号
    private static final long serialVersionUID = 8683452581122892189L;

    // 默认容量大小
    private static final int DEFAULT_CAPACITY = 10;

    // 空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};

    // 用于保存ArrayList中数据的数组
    private transient Object[] elementData;

    // ArrayList中所包含元素的个数
    private int size;
    //数组的最大容量
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

构造函数

//初始为空数组
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

//根据指定容量,创建个对象数组
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

//直接创建和指定集合一样内容的 ArrayList
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        // c.toArray 有可能不返回一个 Object 数组
        if (elementData.getClass() != Object[].class)
            //使用 Arrays.copy 方法拷创建一个 Object 数组
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        // replace with empty array.
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

扩容方法

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // 1.5 倍 原来容量
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    //如果当前容量还没达到 1.5 倍旧容量,就使用当前容量    
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;


    if (newCapacity - MAX_ARRAY_SIZE > 0)
        //最大容量可以是 Integer.MAX_VALUE
        newCapacity = hugeCapacity(minCapacity);

       elementData = Arrays.copyOf(elementData, newCapacity);
}

ArrayList常用方法
add

public boolean add(E e) {
    //对数组的容量进行调整
    ensureCapacityInternal(size + 1);  
    elementData[size++] = e;
    return true;
}

//在指定位置添加一个元素
public void add(int index, E element) {
    rangeCheckForAdd(index);

    //对数组的容量进行调整
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    //整体后移一位
    System.arraycopy(elementData, index, elementData, index + 1,
                     size - index);
    elementData[index] = element;
    size++;
}
//添加一个集合
public boolean addAll(Collection<? extends E> c) {
    //把该集合转为对象数组
    Object[] a = c.toArray();
    int numNew = a.length;
    //增加容量
    ensureCapacityInternal(size + numNew);  // Increments modCount
    //挨个向后迁移
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    //新数组有元素,就返回 true
    return numNew != 0;
}


查询,修改等操作

E elementData(int index) {
    return (E) elementData[index];
}//根据下标返回值

//获取
public E get(int index) {
    rangeCheck(index);
    //直接根据数组角标返回元素
    return elementData(index);
}

//修改
public E set(int index, E element) {
    rangeCheck(index);
    E oldValue = elementData(index);

    //直接对数组操作
    elementData[index] = element;
    //返回原来的值
    return oldValue;
}

删除操作

//根据下标删除
public E remove(int index) {
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    //挨个往前移一位
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    //原数组中最后一个元素删掉
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

//根据值删除
public boolean remove(Object o) {
    if (o == null) {
        //挨个遍历找到目标
        for (int index = 0; index < size; index++)
            if (elementData[index] == null) {                
                fastRemove(index);
                return true;
            }
    } else {
        for (int index = 0; index < size; index++)
            if (o.equals(elementData[index])) {
                fastRemove(index);
                return true;
            }
    }
    return false;
}
//快速删除
private void fastRemove(int index) {
    modCount++;
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // 
}
//清楚全部
public void clear() {
    modCount++;
    //并没有直接使数组指向 null,而是逐个把元素置为空
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}

Toarray方法


public Object[] toArray() {
    return Arrays.copyOf(elementData, size);
}

public <T> T[] toArray(T[] a) {
    //如果只是要把一部分转换成数组
    if (a.length < size)
        // Make a new array of a's runtime type, but my contents:
        return (T[]) Arrays.copyOf(elementData, size, a.getClass());
    //全部元素拷贝到 数组 a
    System.arraycopy(elementData, 0, a, 0, size);
    if (a.length > size)
        a[size] = null;
    return a;
}

其他的一些方法

//返回长度
public int size() {
        return size;
    }
//判断是否为空
 public boolean isEmpty() {
        return size == 0;
    }
//判断是否存在某个元素
public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
// 返回某个元素的下标
    public int indexOf(Object o) {
        //先判断o是否为空,再根据情况进行遍历整个ArrayList
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

LinkedList

LinkedList是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
LinkedList 实现 List 接口,Deque接口,Cloneable接口,java.io.Serializable接口

成员变量

//LinkedList中元素的数量
transient int size = 0;
//第一个元素
transient Node<E> first;
//最后一个元素
transient Node<E> last;

构造函数

public LinkedList() {
    }
    //有参构造
public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }

插入方法

public boolean addAll(int index, Collection<? extends E> c) {
        checkPositionIndex(index);
        //把c转化成数组
        Object[] a = c.toArray();
        int numNew = a.length;
        //如果数组中没有元素,返回false
        if (numNew == 0)
            return false;

        Node<E> pred, succ;
        if (index == size) {
        //如果index为size,那么index位置上的node为null,node的前一个节点是last
            succ = null;
            pred = last;
        } else {
        //找到当前index位置上的node,用succ表示。pred表示当前节点的前一个节点
            succ = node(index);
            pred = succ.prev;
        }
        for (Object o : a) {
            @SuppressWarnings("unchecked") E e = (E) o;
            Node<E> newNode = new Node<>(pred, e, null);
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            pred = newNode;
        }

        if (succ == null) {
            last = pred;
        } else {
            pred.next = succ;
            succ.prev = pred;
        }

        size += numNew;
        modCount++;
        return true;
    }
//上面的方法就是把c中所有的元素插入LinkList

//将元素添加到第一个位置
public void addFirst(E e) {
        linkFirst(e);
    }
//将元素添加到最后
public void addLast(E e) {
        linkLast(e);
}
//add方法和addlast差不多
public boolean add(E e) {
        linkLast(e);
        return true;
    }
//将元素添加到指定位置
public void add(int index, E element) {
        //检查合法性
        checkPositionIndex(index);
        //如果是添加在最后一个位置,直接调用linkLast
        if (index == size)
            linkLast(element);
        else
        //如果不是的话就需要调用linkBefore
            linkBefore(element, node(index));
    }


//头插法
private void linkFirst(E e) {
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

  //尾插法
  void linkLast(E e) {
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

获取值的方法

//得到第一个元素
 public E getFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return f.item;
    }

//得到最后一个元素
public E getLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return l.item;
    }

  //根据下标获取
  public E get(int index) {
        //检查下标合法性
        checkElementIndex(index);

        return node(index).item;
    }
    //

删除方法

//根据下标删除
 public E remove(int index) {
        //先检查下标合法性
        checkElementIndex(index);
        //直接先调用node获取到节点,然后用unlink删除掉
        return unlink(node(index));
    }
//根据值来删除
public boolean remove(Object o) {
        //根据不同情况进行比较
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null) {
                    unlink(x);
                    return true;
                }
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item)) {
                    unlink(x);
                    return true;
                }
            }
        }
        return false;
    }

//删除最后一个元素
public E removeLast() {
        final Node<E> l = last;
        if (l == null)
            throw new NoSuchElementException();
        return unlinkLast(l);
    }

//删除第一个元素
 public E removeFirst() {
        final Node<E> f = first;
        if (f == null)
            throw new NoSuchElementException();
        return unlinkFirst(f);
    }
  //删除第一个元素
public E poll() {
        final Node<E> f = first;
        return (f == null) ? null : unlinkFirst(f);
    }
//删除第一个元素
public E remove() {
        return removeFirst();
    }
//清空操作
 public void clear() {
        for (Node<E> x = first; x != null; ) {
            //获得某个节点的下一个节点之后就清除此节点的所有信息
            Node<E> next = x.next;
            x.item = null;
            x.next = null;
            x.prev = null;
            x = next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }



其他方法

//判断是否存在某个元素
public boolean contains(Object o) {
        return indexOf(o) != -1;
    }
//通过传入的元素查找下标


public int indexOf(Object o) {
        int index = 0;
        if (o == null) {
            for (Node<E> x = first; x != null; x = x.next) {
                if (x.item == null)
                    return index;
                index++;
            }
        } else {
            for (Node<E> x = first; x != null; x = x.next) {
                if (o.equals(x.item))
                    return index;
                index++;
            }
        }
        return -1;
    }


ArrayList是基于数组实现的,LinkedList是基于链表实现的
ArrayList便于查询,在插入和删除的时候效率较低
LinkedList便于插入和删除,但是查询时效率较低

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值