java集合类——List

总览

在这里插入图片描述
上面是java 基本容器的继承图

接口

Iterable

public interface Iterable<T> {
	// 返回一个 Iterator 对象
    Iterator<T> iterator();
	// 接口默认方法,实现类 Iterator 接口的 就可以使用 list.forEach(i->{dosomething});
	// java 1.8
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
	// 可分割的迭代器
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

Iterator

public interface Iterator<E> {
	// 判断是否还有下一个元素
	boolean hasNext();
	// 获取下一个元素
	E next();
	// 默认方法,若要支持remove操作,需要被重写
	default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    // 对剩下的遍历
	default void forEachRemaining(Consumer<? super E> action) {
	    Objects.requireNonNull(action);
	    while (hasNext())
	        action.accept(next());
	}
}

ListIterator

public interface ListIterator<E> extends Iterator<E> {
    // Query Operations
	// 同Iterator接口
    boolean hasNext();
	// 获取下一个
    E next();
    // 是否有前一个
    boolean hasPrevious();
	// 获取前一个
    E previous();
	// 下一个元素的下标
    int nextIndex();
    // 前一个元素的下标
    int previousIndex();
    // 移除
    void remove();
    // 替换最后一个
    void set(E e);
    // 添加一个新的元素
    void add(E e);
}

Collection

public interface Collection<E> extends Iterable<E> {
    // Query Operations
    // 返回大小
    int size();
    // 判断是否为空
    boolean isEmpty();
    // 判断是否包含Object o
    boolean contains(Object o);
    // 返回迭代器
    Iterator<E> iterator();
    // 返回数组的形式
    Object[] toArray();
    // 传入数组引用,返回被填充的数组
    <T> T[] toArray(T[] a);
	// 添加新的元素
    boolean add(E e);
    // 移除元素
    boolean remove(Object o);
	// c是否是该对象的子序列
    boolean containsAll(Collection<?> c);
    // 将c全部的元素添加
    boolean addAll(Collection<? extends E> c);
    // 移除含有c内的元素
    boolean removeAll(Collection<?> c);
    // 根据条件移除 java 1.8
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
    // 与c取交集
    boolean retainAll(Collection<?> c);
    // 移除所有元素
    void clear();
    // 比较
    boolean equals(Object o);
    // 返回hashCode
    int hashCode();
    // 返回一个可分割的迭代器
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    // 获取Stream对象
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
	// java 1.8 获取并行的Stream对象
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

List

在这里插入图片描述

Queue

public interface Queue<E> extends Collection<E> {
    // 向队列里面添加元素
    boolean add(E e);
    // 插入元素,当抛出异常的时候插入失败
    boolean offer(E e);
    // 移除队列的头,并返回元素,会抛出异常
    E remove();
    // 移除队列的头,并返回元素
    E poll();
    // 会返回第一个元素,但不会删除,如果队列是空但,则抛出移除
    E element();
    // 会返回第一个元素,但不会删除,不会抛出移除
    E peek();
}

Deque

public interface Deque<E> extends Queue<E> {
    // 从头部添加
    void addFirst(E e);
    // 从尾部添加
    void addLast(E e);
    // 从头部添加
    boolean offerFirst(E e);
    // 从尾部添加
    boolean offerLast(E e);
    // 移除第一个
    E removeFirst();
    // 移除最后一个
    E removeLast();
    // 移除第一个
    E pollFirst();
    // 移除最后一个
    E pollLast();
    // 得到第一个
    E getFirst();
    // 得到最后一个
    E getLast();
    // 得到第一个
    E peekFirst();
    // 得到最后一个
    E peekLast();
    // 移除第一个出现但
    boolean removeFirstOccurrence(Object o);
    // 移除最后出现但
    boolean removeLastOccurrence(Object o);
    // *** 栈方法 ***
    // 往栈里push
    void push(E e);
    // 从栈移除
    E pop();
    // *** 集合类方法 ***
    // 删除
    boolean remove(Object o);
    // 是否包含
    boolean contains(Object o);
    // 大小
    public int size();
    // 返回迭代器
    Iterator<E> iterator();
    // 降序迭代器
    Iterator<E> descendingIterator();
}

抽象类

代码过多 挑着说

AbstractCollection

在这里插入图片描述
AbstractCollection 对Collection里面的非特性方法进行了默认实现。

AbstractList

在这里插入图片描述
AbstractList 对 AbstractCollection进行了继承,同时实现了List。
接口的继承可以理解为 方法的沉淀。

AbstractSequentialList

在这里插入图片描述
我们熟悉的有LinkedList是继承 AbstractSequentialList 的。

具体类

LinkedList

在这里插入图片描述
LinkedList 是由链表实现的,所以链表中的单个元素就是链表节点。

// 很简单的双向链表节点结构
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 boolean offer(E e) {
	// 调用add方法
    return add(e);
}
// 调用linkLast
public boolean add(E e) {
    linkLast(e);
    return true;
}
// 真正的方法
void linkLast(E e) {
	// l指向了最后一个
    final Node<E> l = last;
    // 创建新的节点
    final Node<E> newNode = new Node<>(l, e, null);
    // 最后节点的引用指向 新节点
    last = newNode;
    // 如果l是null的话,说明list 里面还没有一个元素
    if (l == null)
    	// first也指向新的元素
        first = newNode;
    else
    	// 如果不是新的元素,则last.next 指向新node
        l.next = newNode;
    // size+1
    size++;
    // 这个字段是从AbstractList继承下来的,表示list被修改的次数+1
    modCount++;
}

// 队列的方式,从尾部进,从头部删
public E poll() {
	// f指向头
    final Node<E> f = first;
    // 如果没有元素返回null,不然就删除f
    return (f == null) ? null : unlinkFirst(f);
}
 private E unlinkFirst(Node<E> f) {
     // assert f == first && f != null;
     // 存储头的元素值到 element
     final E element = f.item;
     // next 指向f的next
     final Node<E> next = f.next;
     f.item = null;
     f.next = null; // help GC 有助于gc
     first = next;
     // 如果next为null,list里面没有元素了,last也指向null
     if (next == null)
         last = null;
     else
     	// 将next的前一个节点置为null
         next.prev = null;
     // 大小-1
     size--;
     // 操作数+1
     modCount++;
     // 返回数据
     return element;
 }

// 不做介绍了
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 peek() {
    final Node<E> f = first;
    return (f == null) ? null : f.item;
}
public E element() {
    return getFirst();
}

ArrayList

相对LinkedList来说,ArrayList会比较复杂点,因为ArrayList里面使用数组来存储的,但是平常情况下我们数组的大小是一开始申请好的,所以这里就涉及到了,数组扩容的问题。

/**
 * Default initial capacity.
 * 默认初始化的大小
 */
private static final int DEFAULT_CAPACITY = 10;
private static final Object[] 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);
    }
}
// 默认的空数组
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

// 增加一个新的元素
public boolean add(E e) {
	// 方法翻译过来就是:确保内部容量
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
// 可以看到这是一个私有方法
private void ensureCapacityInternal(int minCapacity) {
	// ensureExplicitCapacity 确保明确的容量
	// calculateCapacity 计算容量
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
	// 如果数组是空的,则在默认数组大小和传入的size+1 比较,取最大值
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
    // overflow-conscious code
    // 如果最少需要的容器容量大于了现有数组的长度,则需要的数组进行增长
    if (minCapacity - elementData.length > 0)
    	// 数组扩容
        grow(minCapacity);
}
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 对数组的大小进行1.5倍的增长,如果是小数就取整,舍去小数点后的(不是四舍五入)
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 如果扩容后的大小还是比 需要的大小要小
    if (newCapacity - minCapacity < 0)
    	// 则设置成 至少需要的大小
        newCapacity = minCapacity;
	// 如果容量比 Integer.MAX_VALUE - 8 整数最大值-8还大       
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    	// 则取最大值
        newCapacity = hugeCapacity(minCapacity);
    // 将老的数据复制到扩容后的新数组去
    elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
	// 超出整数范围,整数会溢出,变成负数
    if (minCapacity < 0) // overflow
    	// 抛出异常
        throw new OutOfMemoryError();
	// 取最大值
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}

public E remove(int index) {
	// 范围检查
    rangeCheck(index);
    // 操作数+1
    modCount++;
    // 得到需要返回数据
    E oldValue = elementData(index);
    // 这里是需要的数组进行移动,移动的数是 size - index - 1
    int numMoved = size - index - 1;
    // 将index+1位置开始,长度为numMoved的 elementData 数组的数据移动到 index 开始
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    // 帮助gc                     
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}
private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
// 得到特定下标的元素
E elementData(int index) {
    return (E) elementData[index];
}

// 方法上面介绍过了
public E get(int index) {
    rangeCheck(index);
    return elementData(index);
}

Vector

synchronized 版的 arrayList,方法各种同步,效率肯定是很低的。

Stack

满足先进后出
class Stack extends Vector
继承自vector,所以他内部也是数组实现的
push 就是在数组后面增加元素
pop 就是将数组的最后一个元素删除。

public E push(E item) {
    addElement(item);
    return item;
}

public synchronized E pop() {
    E       obj;
    int     len = size();
    obj = peek();
    removeElementAt(len - 1);
    return obj;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值