【Java】の基础——LinkedList和ArrayList

Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。

Collection

Collection的爸爸

Collection接口继承Iterrable接口,
Iterrable:提供迭代的功能

public interface Iterable<T> {
    Iterator<T> iterator();
}

Iterator:迭代器,用于遍历一个序列类似一个游标。
public Interface Iterator{
boolean hasNext();
   Object next();
   void remove();
}

Collection的宝宝

看完了Collection的来历,我们再看看的延伸:
Collection

public interface Collection<E> extends Iterable<E> {}

它是一个接口,是高度抽象出来的集合,它包含了集合的基本操作:添加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。
Collection接口包含了List和Set两大分支。

  1. List是一个有序的队列,每一个元素都有它的索引。第一个元素的索引值是0。
    List的实现类有LinkedList, ArrayList, Vector, Stack。
  2. Set是一个不允许有重复元素的集合。
    Set的实现类有HastSet和TreeSet。HashSet依赖于HashMap,它实际上是通过HashMap实现的;TreeSet依赖于TreeMap,它实际上是通过TreeMap实现的。

List是有序的队列,List中可以有重复的元素;
Set是数学概念中的集合,Set中没有重复元素。

List

public interface List<E> extends Collection<E> {}

List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。List中允许有重复的元素。

Set

public interface Set<E> extends Collection<E> {}

Set是数学概念中的集合,Set中没有重复元素。

ArrayList

ArrayList 实现了动态数组,它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。
遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低。

ArrayList的Add扩容

在add时,先确认数组长度是否足够(这个过程首先检查内部数组是否为空,如果为空就设定默认的初始容量(10) ),接着判断当前需要的容量是否大于内部数组,大于的话就进行扩容。
扩容的过程是,将内部数组拷贝到一个新的大小为原数组1.5倍的数组中(这里也要先计算,来判断扩容后是否会过大,出现溢出等情况),然后将内部数组的引用改为新数组。

LinkedList

双向链表,定义了Node(Entry — 1.8之前)

LinkedList的Add扩容:

JDK1.8之前:

不得不说它的addBefore方法 addBefore(E e, Entry entry)
就是在entry结点之前插入一个新的结点存放e。

public boolean add(E e) {
    addBefore(e, header);
    return true;
}
public void add(int index, E element) {
     addBefore(element, (index==size ? header : entry(index)));
}
public void addFirst(E e) {
    addBefore(e, header.next);
}
public void addLast(E e) {
    addBefore(e, header);
}

JDK1.8:

public boolean add(E e) {
        // 添加到末尾
        linkLast(e);
        return true;
   }
void linkLast(E e) {
        // 保存尾结点,l为final类型,不可更改
        final Node<E> l = last;
        // 新生成结点的前驱为l,后继为null
        final Node<E> newNode = new Node<>(l, e, null);
        // 重新赋值尾结点
        last = newNode;    
        if (l == null) // 尾结点为空
            first = newNode; // 赋值头结点
        else // 尾结点不为空
            l.next = newNode; // 尾结点的后继为新生成的结点
        // 大小加1    
        size++;
        // 结构性修改加1
        modCount++;
    }

当然,它也提供了LinkFirst()插入第一个元素,LinkBefore()来插入元素等方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章