栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java集合源码分析(Collection、List、ArrayList、未完)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java集合源码分析(Collection、List、ArrayList、未完)

集合源码阅读

这里的图片罗列了接下来需要学习的内容,我的话首先从List入手

Collection接口

作为Java中所有集合的根接口,Collection中规定的基本内容并不多,我们首先看源码中官方的描述

The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and others unordered. The JDK does not provide any direct implementations of this interface: it provides implementations of more specific subinterfaces like Set and List. This interface is typically used to pass collections around and manipulate them where maximum generality is desired.

集合层次结构中的根接口。集合表示了一组对象,并称其为元素。有些集合允许重复元素(ArrayList,linkedList…),而有些则不允许(HashMap,TreeSet…),有些是有序的,有些是无序的。JDK并不提供这个接口的任何直接实现: 它提供更具体的子接口(如Set和List)的实现。这个接口通常用于传递集合,并且用在需要最大通用性的地方对其操作

public interface Collection extends Iterable {
    
    int size();
    
    boolean isEmpty();
    
    boolean contains(Object o);
    
    Iterator iterator();
    
    Object[] toArray();
    
     T[] toArray(T[] a);
    

    boolean add(E e);
     
    boolean remove(Object o);
     
    boolean containsAll(Collection c);
       
    boolean addAll(Collection c);
      
    boolean removeAll(Collection c);

    default boolean removeIf(Predicate filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
    

    boolean retainAll(Collection c);

    void clear();

    boolean equals(Object o);

    int hashCode();
    
    @Override
    default Spliterator spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    default Stream stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    default Stream parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}
List接口作用

可以看出List集合直接继承Collection集合,包含了集合的最基本的一些特征方法,我们来看一下官方对List的描述

An ordered collection (also known as a sequence). The user of this interface has precise control over where in the list each element is inserted. The user can access elements by their integer index (position in the list), and search for elements in the list.List

有序的集合(也称为序列)。此界面的用户可以精确控制每个元素在列表中的插入位置。用户可以通过整数索引(在列表中的位置)访问元素,并在列表中搜索元素。

官方对List的描述是不是很像数组,虽然它确实有些地方和数组非常相似,但是还是有非常大的不同,比如有些实现按照索引查找的时间是和索引大小成正比的。是不是很像链表,没错,List的大部分实现都能看见链表的影子,因此站在链表的角度理解可能会更轻松一些。

public interface List extends Collection {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator iterator();
    Object[] toArray();
     T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection c);
    boolean addAll(Collection c);
    boolean addAll(int index, Collection c);
    boolean removeAll(Collection c);
    boolean retainAll(Collection c);
    
    default void replaceAll(UnaryOperator operator) {
            Objects.requireNonNull(operator);
            final ListIterator li = this.listIterator();
            while (li.hasNext()) {
                li.set(operator.apply(li.next()));
            }
        }
    default void sort(Comparator c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
    void clear();
    boolean equals(Object o);
    int hashCode();
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);
    int indexOf(Object o);
    int lastIndexOf(Object o);
    ListIterator listIterator();
    ListIterator listIterator(int index);
    List subList(int fromIndex, int toIndex);
     @Override
    default Spliterator spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }
}
ArrayList源码分析

惯例,看看官方的解释

Resizable-array implementation of the List interface. Implements all optional list operations, and permits all elements, including null. In addition to implementing the List interface, this class provides methods to manipulate the size of the array that is used internally to store the list. (This class is roughly equivalent to Vector, except that it is unsynchronized.)
The size, isEmpty, get, set, iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time, that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the linkedList implementation.
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.

(机翻)列表接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括null。除了实现List接口之外,这个类还提供了一些方法来操纵数组的大小,数组在内部用于存储列表(这个类大致相当于Vector,只是它是不同步的。)
size、isEmpty、get、set、iterator和listIterator操作以固定时间运行。add操作以摊销的固定时间运行,也就是说,添加n个元素需要O(n)时间。所有其他操作都在线性时间内运行(粗略地说)。与linkedList实现相比,常量因子较低。
每个ArrayList实例都有一个容量。容量是用于存储列表中元素的数组的大小。它总是至少和列表大小一样大。当元素添加到ArrayList时,它的容量会自动增长。除了添加一个元素具有固定的摊余时间成本这一事实之外,增长策略的细节没有被指定。
后面主要说ArrayList是线程不安全的,如果需要在并发情况下使用该集合,需要使用synchronizedList包装起来。达到线程安全的目的,虽然会损失一部分性能。

继承实现关系
public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable
  • ArrayList继承AbstractList类,实现了List接口, 所有有List的所有功能。
  • ArrayList实现了RandomAccess接口,支持随机访问,可以直接通过下标进行访问。
  • ArrayList实现了Cloneable接口,支持克隆。
  • ArrayList实现了Serializable接口,支持序列化功能。
常量的意义
    private static final long serialVersionUID = 8683452581122892189L;
    //默认初始化容量
    private static final int DEFAULT_CAPACITY = 10;
    //用于空实例的共享空数组实例。
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //用于默认大小的空实例的共享空数组实例。我们将其与空元素数据区分开来,以了解添加第一个元素时要扩容多少。
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    //存储ArrayList元素的数组缓冲区。ArrayList的容量是此数组缓冲区的长度。
    //transient在序列化时不会被序列化,缓冲区不会被保存
    transient Object[] elementData; // non-private to simplify nested class access
    //ArrayList的大小
    private int size;
   
构造方法
public ArrayList(int initialCapacity) {
    //指定大小大于0 ,就直接实例化。
    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 ArrayList(Collection c) {
    elementData = c.toArray();//如果c为空,则会抛出空指针异常
    if ((size = elementData.length) != 0) {
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

  • 通过构造方法可以看出,如果不指定容量,初始化ArrayList的容量为0
  • 在指定容量时,是根据指定容量大小来实例化集合的,不会采用默认的10
添加元素的方法
public E set(int index, E element) {}
public boolean add(E e) {}
public void add(int index, E element) {}
public boolean addAll(Collection c) {}   
public boolean addAll(int index, Collection c) {}

具体内容

public E set(int index, E element) {
    //下标检查
    rangeCheck(index);
    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}


public boolean add(E e) {
    //确保容量足够
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    //计算容量
    int capacity = calculateCapacity(elementData, minCapacity);//10
    ensureExplicitCapacity(capacity);
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    //这一个条件成立的情况只有初始化时未指定大小,并且是第一个次添加元素
    //即:ArrayList list = new ArrayList();
    // list.add(1); 能通过这个条件
    // list.add(2); 不能通过这个条件
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //不明白为什么要在DEFAULT_CAPACITY和minCapacity中选出最大的,理论上能进入  
        //这里就是第一次添加元素,直接默认10不就行了吗?
        return Math.max(DEFAULT_CAPACITY, minCapacity); 1 ==> 10
    }
    return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
    //这个是AbstractList里继承下来的,具体作用和迭代有关
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)//第一次之后,elementData.length,就是10
        grow(minCapacity);//10
}

private void grow(int minCapacity) {//
    // overflow-conscious code
    int oldCapacity = elementData.length;//
    int newCapacity = oldCapacity + (oldCapacity >> 1);//  按照1.5倍的方法进行扩容
    //这个if是防止有负值的出现,有可能超出int的范围。
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    if (newCapacity - MAX_ARRAY_SIZE > 0)    
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

//数组的最大容量不会超过MAX_ARRAY_SIZE
private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}








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

//数组的最大容量不会超过MAX_ARRAY_SIZE
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/445949.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号