chap09-Lists

java collections 学习笔记

Set接口是最简单的集合类型(因为它没有向Collection添加额外的方法).
而List则不然,List以及其实现类:ArrayListLinkedList.
除了 Collection提供的集合的基本功能外,List接口还增加了对集合的index(位置)访问的方法。
因此,当从List中检索元素时,可以不使用迭代器去访问元素,而是使用index来访问。
注意:与Set不同,List支持存储重复元素
在这里插入图片描述

VectorStack在之前的章节已经分析过,这里不再分析。
这里需要注意的是:Vector线程安全的集合类

List

<<java.utl.List>>

public interface List<E> extends Collection<E> {
    // 继承自Collection的接口
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);

    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);

    boolean removeAll(Collection<?> c);
    boolean retainAll(Collection<?> c);

    void clear();
    boolean equals(Object o);
    int hashCode();

    
    List新增的方法
   
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
     //在index之后,插入c
    boolean addAll(int index, Collection<? extends E> c);
    E remove(int index);
    int indexOf(Object o);
    int lastIndexOf(Object o);

    ListIterator<E> listIterator();
    //从指定位置开始获取ListIterator
    ListIterator<E> listIterator(int index);

    // 获取一个子List,  [fromIndex,toIndex)
    //若fromIndex == toIndex,返回为empty;
    List<E> subList(int fromIndex, int toIndex);
}

<<java.utl.ListIterator>>

列表迭代器,允许程序员按任一方向遍历列表、迭代期间修改列表,并获得迭代器在列表中的当前位置。

public interface ListIterator<E> extends Iterator<E> {
    //继承自 Iterator
    boolean hasNext();
    E next();
    void remove();
    
    //正向遍历时使用
    int nextIndex();   

    //反向遍历时使用
    boolean hasPrevious();
    //返回前一个元素。
    E previous();
    int previousIndex();

   
    void set(E e);
    void add(E e);
}

AbstractList

内部类:Itr

private class Itr implements Iterator<E> {
	//游标
    int cursor = 0;
    //执行完next()后的index,即上一次的index;
    int lastRet = -1;
    
    //fast-fail机制: 为了防止遍历过程中被其他线程线程更新;
    int expectedModCount = modCount;

    public boolean hasNext() {
        return cursor != size();
    }

    public E next() {
        checkForComodification();
        try {
            int i = cursor;
            E next = get(i);
            lastRet = i;
            //执行完后,cursor += 1
            cursor = i + 1;
            return next;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }

    public void remove() {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
        	//调用外部的的remove()方法
            AbstractList.this.remove(lastRet);
            if (lastRet < cursor)
                cursor--;
            lastRet = -1;
            //更新modCount
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException e) {
            throw new ConcurrentModificationException();
        }
    }

    final void checkForComodification() {
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
    }
}

内部类:ListItr

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public E previous() {
        checkForComodification();
        try {
            int i = cursor - 1;
            E previous = get(i);
            lastRet = cursor = i;
            return previous;
        } catch (IndexOutOfBoundsException e) {
            checkForComodification();
            throw new NoSuchElementException();
        }
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor-1;
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            AbstractList.this.set(lastRet, e);
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            AbstractList.this.add(i, e);
            lastRet = -1;
            cursor = i + 1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

内部类: SubList

subList()方法返回的是AbstractList的内部类 SubList,它是源List的一个视图
对于 SubList 子列表的所有操作最终会反映到原列表上。

class SubList<E> extends AbstractList<E> {
	//记录源List
    private final AbstractList<E> l;
    
    private final int offset;
    private int size;

    SubList(AbstractList<E> list, int fromIndex, int toIndex) {
        if (fromIndex < 0)
            throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
        if (toIndex > list.size())
            throw new IndexOutOfBoundsException("toIndex = " + toIndex);
        if (fromIndex > toIndex)
            throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                               ") > toIndex(" + toIndex + ")");
        l = list;
        offset = fromIndex; 
        size = toIndex - fromIndex;
        this.modCount = l.modCount;
    }
    
    //this.set(0) == l.set(0+offset);
    public E set(int index, E element) {
        rangeCheck(index);
        checkForComodification();
        return l.set(index+offset, element);
    }
    
    public int size() {
        checkForComodification();
        return size;
    }
    
    //其他方法略...................
    
}

RandomAccessSubList

class RandomAccessSubList<E> extends SubList<E> implements RandomAccess {
    RandomAccessSubList(AbstractList<E> list, int fromIndex, int toIndex) {
        super(list, fromIndex, toIndex);
    }

    public List<E> subList(int fromIndex, int toIndex) {
        return new RandomAccessSubList<>(this, fromIndex, toIndex);
    }
}

AbstractList

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
    protected transient int modCount = 0;

    protected AbstractList() {
    }

    //默认添加到末尾
    public boolean add(E e) {
        add(size(), e);
        return true;
    }

    abstract public E get(int index);

    public E set(int index, E element) {
        throw new UnsupportedOperationException();
    }
   
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

    public E remove(int index) {
        throw new UnsupportedOperationException();
    }


    //正向查找时,当it.next() == o时,返回previousIndex;
    public int indexOf(Object o) {
        ListIterator<E> it = listIterator();
        if (o==null) {
            while (it.hasNext())
                if (it.next()==null)
                    return it.previousIndex();
        } else {
            while (it.hasNext())
                if (o.equals(it.next()))
                    return it.previousIndex();
        }
        return -1;
    }

    //反向查找: 当it.previous() == o时,返回nextIndex;
    public int lastIndexOf(Object o) {
        ListIterator<E> it = listIterator(size());
        if (o==null) {
            while (it.hasPrevious())
                if (it.previous()==null)
                    return it.nextIndex();
        } else {
            while (it.hasPrevious())
                if (o.equals(it.previous()))
                    return it.nextIndex();
        }
        return -1;
    }


    // Bulk Operations
    public void clear() {
        //[0,size()) 范围内数据清空
        removeRange(0, size());
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        boolean modified = false;
        for (E e : c) {
            add(index++, e);
            modified = true;
        }
        return modified;
    }

    // Iterators
    public Iterator<E> iterator() {
        return new Itr();
    }
   
    public ListIterator<E> listIterator() {
        return listIterator(0);
    }

    //从index开始遍历...
    public ListIterator<E> listIterator(final int index) {
        rangeCheckForAdd(index);
        return new ListItr(index);
    }

    //注意:AbstarctList 并没有implements RandomAccess接口;
    public List<E> subList(int fromIndex, int toIndex) {
        return (this instanceof RandomAccess ?
                new RandomAccessSubList<>(this, fromIndex, toIndex) :
                new SubList<>(this, fromIndex, toIndex));
    }

    //删除[fromIndex,toIndex)范围内元素;
    protected void removeRange(int fromIndex, int toIndex) {
        ListIterator<E> it = listIterator(fromIndex);
        for (int i=0, n=toIndex-fromIndex; i<n; i++) {
            it.next();
            it.remove();
        }
    }

    private void rangeCheckForAdd(int index) {
        if (index < 0 || index > size())
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    // size()相等,且每一个对应的位置的元素equal
    public boolean equals(Object o) {
        //略
    }

    public int hashCode() {
        //略..
    }
    
}


ArrayList

ArrayList类是Collection Framework针对Vector类的替代.
他们的功能相同,且他们都是以数组的方式来有序的(按照插入的顺序,不是排序)存储数据。
他们最主要区别在于默认情况下ArrayList使用不同步,而Vector是synchronized
List对数据的随机访问效率较高,但是对插入和删除元素比较慢
如果需要经常的添加和删除元素,考虑使用LinkedList.

构造函数

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
    //默认容量为10
    private static final int DEFAULT_CAPACITY = 10;
    
    //空数组常量
    private static final Object[] EMPTY_ELEMENTDATA = {};

    //默认长度的空数组 常量
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    //非私有变量,子类可以访问
    transient Object[] elementData; 

    private int size;

    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    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);
        }
    }

    public ArrayList() {
        //参数为空的构造函数,返回 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

  
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
}

添加元素

//添加方法..
public boolean add(E e) {
     //确保容量可用,如果容量不够用则grow,返回新的长度的新数组
     //然后使用Arrays.copy()将原有数组内容copy到新的数组中
    ensureCapacityInternal(size + 1); 
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    //计算所需的最小capacity
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //注意这里使用的 Max.max(a,b);  --- “矮子里选将军”
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    //如果需要的最小容量 > 数组当前长度,则grow
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);

    //newCapacity大小判断,略...
    elementData = Arrays.copyOf(elementData, newCapacity);
}


 public void add(int index, E element) {
    //if (index > size || index < 0) 则抛出异常
    rangeCheckForAdd(index);

    ensureCapacityInternal(size + 1); 
    //[index,size)区间的元素向后移动一位,[index+1,size+1)
    System.arraycopy(elementData, index, elementData, index + 1, size - index);
    
    //index位置设置为 element                
    elementData[index] = element;
    size++;
}


//当c为空时,返回false. (略....)
public boolean addAll(Collection c)
public boolean addAll(int index, Collection c)

删除元素

 /删除元素
//List每一个元素设为null,size设为0
public void clear() ;

//若o 存在,则返回ture
public boolean remove(Object o);

//返回index对应的值;
public Object remove(int index);

public boolean removeAll(Collection<?> c) {
    Objects.requireNonNull(c);
    return batchRemove(c, false);
}

removeAll批量删除操作,内部调用:batchRemove(c, false);

batchRemove()

/**
 * complement:
 *  - false: 表示 removeAll操作
 *  - true: 表示 retainAll操作
 *  
 *  下面分析按照 删除的逻辑 分析,即complement == false
 */
private boolean batchRemove(Collection<?> c, boolean complement) {
    final Object[] elementData = this.elementData;
    int r = 0, w = 0;
    boolean modified = false;
    try {
        for (; r < size; r++)
            //如果c包含elementData[r],则删除 ; 否则保留
            //complement == false; 说明当不包含时执行if(){}内部逻辑
            if (c.contains(elementData[r]) == complement)
                //将需要保留的元素,移动至数组的“头部”位置 ,并将w++;
                elementData[w++] = elementData[r];
    } finally {
        //只有在抛出异常时,r != size;  
        //上述:contains()方法可能会抛出异常
        if (r != size) {
            //此时需要将[0,r)区间的元素移动至[0,w),然后[r,size)区间的元素保留
            //上述的if(){} 已经将[0,r)部分移动至0,w),剩下的需要保留[r,size)部分元素
            System.arraycopy(elementData, r,
                             elementData, w,
                             size - r);
            w += size - r;
        }

        //w != size ,上面for-each 有部分loop没有执行if(){}内部语句: 即发现需要删除的元素
        //将[w,size)区间的元素删除,保留[0,w)范围内元素,此时size == w
        if (w != size) {
            for (int i = w; i < size; i++)
                elementData[i] = null;
            modCount += size - w;
            size = w;
            modified = true;
        }
    }
    return modified;
}

retainAll()
内部调用batchRemove(c, true);

removeRange()

protected void removeRange(int fromIndex, int toIndex) {
    modCount++;
    int numMoved = size - toIndex;
      //[0,size) 改为[0,fromIndex),[toIndex,size) ,删除[fromIndex,toIndex)
    //只需将:[toIndex,size) 移动至[FromIndex, (toIndex - fromIndex)) ,
    System.arraycopy(elementData, toIndex, elementData, fromIndex,
                     numMoved);

    //然后将[size-(toIndex-fromIndex),size) 部分清空即可;
    int newSize = size - (toIndex-fromIndex);
    for (int i = newSize; i < size; i++) {
        elementData[i] = null;
    }
    size = newSize;
}

APIs

 public Iterator iterator()
public ListIterator listIterator()
public ListIterator listIterator(int index)

public boolean contains(Object element)
public boolean containsAll(Collection c)

public int indexOf(Object element)
public int lastIndexOf(Object element)

public Object set(int index, Object element)

public int size()
public boolean isEmpty()

//修剪此ArrayList实例的容量至当前列表实际大小:sizee
    //应用程序可以使用此来减少list的内存占用量;
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}


LinkedList

LinkedList类是一个双向链表,它在内部维护对前一个和下一个元素的引用.
如果需要经常的添加和删除元素,推荐使用LinkedList.

内部类: Node

  private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

构造函数

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
    transient int size = 0;
    
    //记录本linkedlist的头和尾
    transient Node<E> first;
    transient Node<E> last;

    public LinkedList() {
    }

    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);
    }
}

添加元素

add

//默认将元素 插入“队尾”
public boolean add(E e) {
    linkLast(e);
    return true;
}

public void add(int index, E element) {
    // index >= 0 && index <= size
    checkPositionIndex(index);

    if (index == size)
        //插入队尾
        linkLast(element);
    else
        //首先找到index位置的元素,然后将 node插入队列
        linkBefore(element, node(index));
}

当插入时未指定index时,或index == size时,会将新的元素插入队尾linkLast()

linkLast

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    //将新添的元素设置为 last
    last = newNode;

    //如果插入前的last即l == null, 则说明之前列表为空,新插入的节点是first
    if (l == null)
        first = newNode;
    else
        //l的next节点指向新增的节点
        l.next = newNode;
    size++;
    modCount++;
}

linkBefore
当插入index<size时,调用linkBefore方法,在执行此方法之前,首先需要定位index对应的Node

 Node<E> node(int index) {
    //如果index < 0.5 *size,则正向查找: 从first开始寻找...
    if (index < (size >> 1)) {
        Node<E> x = first;
        //执行到(index - 1).next
        for (int i = 0; i < index; i++)
            x = x.next;
        return x;
    } else {
        //如果index = 0.5 *size,则逆向查找: 从last 逆推寻找...
        //执行到: (index+1).prev
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            x = x.prev;
        return x;
    }
}

 //将e 插入到succ 之前
//e.prev = succ.prev ;
//e.next = succ ;
//succ.prev = e;
 void linkBefore(E e, Node<E> succ) {
    // assert succ != null;
    final Node<E> pred = succ.prev;
    final Node<E> newNode = new Node<>(pred, e, succ);
    succ.prev = newNode;
    //pred为空,表示插入的节点为first
    if (pred == null)
        first = newNode;
    else
        pred.next = newNode;
    size++;
    modCount++;
}

其他插入APIs

public void addFirst(E e) ;
public void addLast(E e);

 public boolean addAll(Collection<? extends E> c) {
    return addAll(size, c);
}
public boolean addAll(int index, Collection<? extends E> c);
 
 //返回的是E,不是Node
public E getFirst() {
 final Node<E> f = first;
 if (f == null)
     throw new NoSuchElementException();
 return f.item;
}

public E getLast() ;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值