JDK1.8源码学习 -- 集合Collection

Collection集合UML关系图

集合

队列

Iterable

实现此接口允许对象成为可执行forEach目标。从类中三个方法可以看出实现Iterable接口可以获取到3种迭代元素的方法。

......
public interface Iterable<T> {

    // 返回泛型的顺序迭代器
    Iterator<T> iterator();

    // 对Iterable中的元素进行指定的操作(1.8新添加的方法)
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

    // 返回一个内部元素为T类型的并行迭代器(1.8新添加的方法)
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

Iterator

迭代器。定义集合迭代器的通用方法和默认实现。常规用法循环调用hasNext()方法判断是否有下一个元素,有则调用next()方法获取下一个元素对象执行对应的操作。在1.8版本添加了forEachRemaining(),迭代所有剩余元素并执行给定的操作。

......
public interface Iterator<E> {
    
    /** 判断是否有下一个元素 */
    boolean hasNext();

    /** 返回下一个元素 */
    E next();

    /** 删除当前元素,默认抛出异常 */
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }

    /** 根据当前迭代器的指针迭代剩余元素,并执行给定的操作(1.8新添加)
        每次调用next()方法时,迭代器指针就会向后移动指向下一个元素,
        而调用forEachRemaining()方法时会从当前指针进行迭代 */
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action);
        while (hasNext()) {
            action.accept(next());
        }    
    }
}

Collection

从语法上来讲集合的顶级父类是Iterabled,但实现Iterable只是获得迭代的功能,而Collection接口定义了集合常用的操作方法,值得注意的是Collection中也对子类进行了约定,所有通用Collection实现类(通常通过其子接口之一间接实现集合)都应提供两个“标准”构造函数

一个无参数构造函数,它创建一个空集合。

一个构造函数具有Collection类型的单个参数,它将创建一个具有与其参数相同元素的新集合。实际上,后一个构造函数允许用户复制任何集合,从而生成所需实现类型的等效集合。无法强制执行此约定(因为接口不能包含构造函数),但Java平台库中的所有通用Collection实现都符合此约定。

接口注释中还提示:此接口中包含的“破坏性”方法,即修改其操作的集合的方法,如果此集合不支持该操作,则指定为抛出UnsupportedOperationException。如果调用对集合没有影响,则这些方法可能(但不是必需)抛出UnsupportedOperationExceptio。

public interface Collection<E> extends Iterable<E> {
    
    /** 集合元素数量 */
    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);

    /** 删除此集合中满足给定过滤条件的所有元素 @since 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;
    }

    /** 仅保留此集合中包含在参数集合中的元素,不包含的删除。 */
    boolean retainAll(Collection<?> c);

    /** 删除此集合中的所有元素。此方法返回后,集合将为空。 */
    void clear();


    /** 判断与指定对象是否相等 */
    boolean equals(Object o);

    /** 返回该集合的hashCode值,重写equals()方法必须重写hashCode()方法 */
    int hashCode();

    /** 默认实现从集合中获取可拆分迭代器,Spliterator是为了并行执行而设计的 @since 1.8 */
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }

    /** 默认实返回顺序的Stream,@since 1.8 */
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    /** 默认实现从集合的Spliterator创建一个并行的Stream。@since 1.8 */
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

AbstractCollection

AbstractCollection是一个抽象类,提供Collection部分接口的实现。主要对add和remove类型方法进行了实现,但是add()和remove()直接抛出UnsupportedOperationException异常,表示了默认实现不支持元素增删的操作,也就是默认集合不可修改。

要实现一个不可修改的集合,程序员只需要扩展这个类,并为iterator()和size()方法提供实现(迭代器方法返回的迭代器必须实现hasNext()和next()。

要实现可修改的集合,程序员必须另外重写这个类的add(E)方法(否则会抛出UnsupportedOperationException),而iterator()方法返回的迭代器必须另外实现remove()方法;

根据Collection接口规范中的建议,程序员通常应提供无参数构造方法和集合参数构造方法的实现。

    ......
    // AbstractCollection实现add(E)方法直接抛出异常
    public boolean add(E e) {
        throw new UnsupportedOperationException();
    }
    
    public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    // 使用迭代器默认的删除逻辑
                    // 也就是抛出UnsupportedOperationException异常
                    it.remove();
                    return true;
                }
            }
        }
        ......
        return false;
    }

通过Collections. unmodifiableCollection(Collection c) 方法就可以获得一个UnmodifiableCollection集合,此类中的增删改方法都是抛出UnsupportedOperationException异常,实现不可修改集合。

List

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

List继承了Collection接口,并针对有序性定义了一些基于索引操作的方法。

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

    /** 从指定索引位置添加元素集合 */
    boolean addAll(int index, Collection<? extends E> c);

    /** 将集合中的所有元素执行给定的操作,例如所有字符串大小写转化等 @since 1.8 */
    default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }

    /** 将集合元素按照给定的排序方式排序 @since 1.8 */
    @SuppressWarnings({"unchecked", "rawtypes"})
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }


    /** 获取指定索引位置的元素 */
    E get(int index);

    /** 设置索引位置的元素 */
    E set(int index, E element);

    /** 在指定索引位置添加元素 */
    void add(int index, E element);


    /** 获取元素的索引位置 */
    int indexOf(Object o);

    /** 获取元素最后出现的索引位置 */
    int lastIndexOf(Object o);


    /** 获取ListIterator迭代器,ListIterator是一种列表迭代器,
        允许程序员沿任意方向遍历列表,在迭代期间修改列表,并获取迭代器在列表中的当前位置 */
    ListIterator<E> listIterator();

    /** 获取指定索引位置的ListIterator迭代器 */
    ListIterator<E> listIterator(int index);

    /** 根据给定的索引位置获取元素集合 */
    List<E> subList(int fromIndex, int toIndex);
}

AbstractList

AbstractList是一个抽象类,继承AbstractCollection并实现了List部分接口的实现,默认实现支持“随机访问”数据存储(如数组)的操作,随机访问即可通过索引访问任意一个元素。

要实现一个不可修改的列表,程序员只需要扩展这个类并为get(int)和size()方法提供实现即可。

要实现可修改列表,程序员必须另外重写set(int,Object)、set(int、E)方法(否则会引发UnsupportedOperationException异常)。如果列表大小可变,则程序员必须另外重写add(int,Object)、add(int、E)和remove(int)方法。l

根据Collection接口规范中的建议,程序员通常应提供无参数构造方法和集合参数构造方法的实现。

AbstractSequentialList

AbstractList是一个抽象类,继承AbstractList抽象了,并提供了List部分接口的实现,默认实现支持“顺序访问”数据存储(如链表)的操作,顺序访问即只能按照链表从头到尾或从尾到头的访问。

要实现一个列表,程序员只需要扩展这个类,并为listIterator()和size()方法提供实现即可。

要实现不可修改的列表,程序员只需实现列表迭代器的hasNext()、next(),hasPrevious()和previous()以及previousIndex()方法。

要实现可修改的列表,程序员应该另外实现列表迭代器的set方法。对于可变大小的列表,程序员应该另外实现列表迭代器的remove()和add(E)方法。

根据Collection接口规范中的建议,程序员通常应提供无参数构造方法和集合参数构造方法的实现。

ArrayList

ArrayList继承AbstractList并实现List接口,是Java中比较常用的有序、线程不安全集合,底层数据结构是Object数组,所以能够根据索引进行查询元素查询效率高。但增删效率较低,新增时可能导致底层数组扩容且复制数组,删除时会导致后面的元素进行位移。结合ArrayList的特点一般使用在查询多增删少的场景。

.....
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

    /** 底层就是数组 */
    transient Object[] elementData;

    /** 默认数组初始长度是10 */
    private static final int DEFAULT_CAPACITY = 10;

    /** 记录当前集合内的元素个数 */
    private int size;

    /** 继承AbstractList而来,记录当前集合被修改的次数
        每次add或者remove它的值都会加1 */
    private transient int modCount = 0;

    // 无参数构造方法只会创建一个空数组(除非)
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    // 添加元素方法
    public boolean add(E e) {
        // 验证元素个数+1是否超出数组长度
        // 超出就进行扩容
        ensureCapacityInternal(size + 1);
        // size++
        elementData[size++] = e;
        return true;
    }

    // ArrayList扩容方法
    private void grow(int minCapacity) {
        // 记录原数组大小
        int oldCapacity = elementData.length;
        // oldCapacity >> 1 == oldCapacity / 2 每次扩容原数组大小1.5倍,
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 如果扩容后的大小比限制的数组最大值还要大
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            // 将原大小与限制最大值进行比较,大于限制值就取Integer.MAX_VALUE
            // 否则取限制最大值 Integer.MAX_VALUE - 8
            newCapacity = hugeCapacity(minCapacity);
        // 根据扩容的大小创建一个新数组,并把元素复制到新数组
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    // 删除指定索引元素的方法
    public E remove(int index) {
        // 校验是否索引越界
        rangeCheck(index);
        // 集合修改次数加1
        modCount++;
        // 获取要删除的元素作为返回值
        E oldValue = elementData(index);
        // 计算出删除元素后要拷贝元素个数
        // 例:当前elementData=["a","b","c","d"],我们要删除索引为1的元素也就是b
        // numMoved = 4 - 1 - 1 = 2;也就是删除b后需要拷贝2个元素(c和d)
        int numMoved = size - index - 1;
        if (numMoved > 0)
            // index+1就是从哪个索引开始拷贝,1+1=2也就是从索引2开始拷贝(c)
            // index是要从哪个索引开始填充,也就是索引1的位置开始填充,
            // numMoved拷贝个数
            // 最终拷贝elementData=["a","c","d","d"]
            // 其实简单来讲就是把要删除索引后的元素往前挪一位
            System.arraycopy(elementData,index+1,elementData,index,numMoved);
        // 将最后一个元素设置为null
        elementData[--size] = null; // clear to let GC do its work
        return oldValue;
    }
    
    private class Itr implements Iterator<E> {
        // 记录迭代时下一个元素的索引
        int cursor;   
        // 记录next获取元素的索引    
        int lastRet = -1; 
        // 记录创建迭代器时当前集合修改的次数
        int expectedModCount = modCount;
        
        // 每次add和remove时都要判断记录的修改次数和当前集合的修改次数是否一致
        // 如果不一致代表在迭代过程中集合已经被修改过了就会抛出异常
        // 建议不要在迭代集合时add或remove元素
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
.....
}

LinkedList

LinkedList继承AbstractSequentialList并实现List接口,是Java中常用的有序、线程不安全的双向链表集合。底层使用内部类Node实现,每个Node都记录了上一个和下一个元素对象。新增只需要修改头或尾元素中记录的上或下一个元素即可。删除只需要修改相邻Node中记录的上下元素即可。所以增删效率高。但根据索引获取元素时都需要从头或尾(index<size/2就从头否则从尾)开始迭代Node节点,找到索引位置(第几个)的元素。结合LinkedList的特点一般使用在增删多查询少的场景。

LinkedList还实现了Deque接口,可以当做双端队列来使用,addFirst(E)、addLast(E)队列头、尾插入元素,pollFirst()、pollLast()检索并移除头、尾元素,peekFirst()、peekLast()检索不移除头、尾元素等队列操作。

......
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable {

    // 记录元素个数
    transient int size = 0;

    /** 记录双向链表的头部元素 */
    transient Node<E> first;

    /** 记录双向链表的尾部元素 */
    transient Node<E> last;
    
    // 添加元素
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    // 获取指定索引的元素
    Node<E> node(int index) {
        // 判断从头或尾开始迭代
        if (index < (size >> 1)) {
            Node<E> x = first;
            // 索引对应了链表的第几个
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

    // Deque接口一些方法的实现
    public void push(E e) {
        addFirst(e);
    }
    // 从队列头部弹出一个元素
    public E pop() {
        return removeFirst();
    }
    // 检索不删除
    public E peek() {
        final Node<E> f = first;
        return (f == null) ? null : f.item;
    }
......
}

Vector

Vector整理结构和内部实现类似ArrayList,继承AbstractList抽象类并实现List接口。但Vector中每个可能出现线程安全的方法上加了synchronized关键字,效率低,所以Vector是有序、线程安全的集合。正因为都是在方法上使用synchronized实现线程安全,所以还是会产生一些安全问题,已经不推荐使用。

// 假如有两个线程同时进入contains(e)方法,传递的参数都是一样的,例如 contains("123")。
// 当线程1执行if (!vector.contains(element)) 后还没有执行vector.add(element); 时,
// 线程2进来了,此时vector.contains(element))还是返回false,
// 这样的结果会导致两个123都加入到vector。所以是线程不安全的。
if (!vector.contains(element)) 
    vector.add(element); 
}

综上来说推荐使用Collections.synchronizedList(List<T> list);方法来获取一个线程安全的集合,SynchronizedList是Collections的内部类,它采用在方法内添加synchronized对代码块进行修改,保证同时访问方法的多个线程只会有一个线程执行操作。且SynchronizedList还支持指定锁对象。

......
public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    
    /** 元素数组 */
    protected Object[] elementData;

    /** 元素个数 */
    protected int elementCount;

    /** 每次扩容值,如果扩容值小于或等于零,则默认扩容到原大小的2倍。 */
    protected int capacityIncrement;

    // 默认数组初始大小是10
    public Vector() {
        this(10);
    }

    /** 构造方法,可指定初始数组大小和每次扩容值。 */
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
    
    /** get()方法都添加了synchronized */
    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }

    /** size()方法都添加了synchronized */
    public synchronized int size() {
        return elementCount;
    }
......
}

Set

集合中不包含重复元素,并且最多包含一个null元素是Set最主要的特性,对于是否有序来说默认是无序的,但直接继承了Collection接口并且没有添加新的方法定义。

AbstractSet

AbstractSet是个抽象类,继承AbstractCollection抽象类同时实现Set接口,在此类只实现了equals()、hashCode()以及removeAll()方法。

虽然继承AbstractCollection类但是没有实现add()和remove()方法,所以默认还是一个不可修改的Set集合。如果想实现一个可修改Set集合,那么就需要重写add()和remove()方法。

但值得注意的是所有通过继承该类实现Set类型集合,那么所有子类中的所有方法和构造函数都必须遵守Set接口施加的附加约束元素不可重复且只能保存一个null值

SortedSet

SortedSet继承了Set接口,并定义了comparator()方法,使得该类的子类都要实现此方法返回一个Comparator元素比较器,如果集合中的元素已经实现了Comparable中compareTo(T o)方法,那么可以在comparator()方法返回null,就会默认使用元素的compareTo(T o)方法。集合的迭代器将按升序元素顺序遍历集合。

......
public interface SortedSet<E> extends Set<E> {
    /** 返回元素比较器 */
    Comparator<? super E> comparator();
    
    /** 返回此集合的部分元素集合,其元素范围从fromElement(含)到 toElement(不含)。 
    (如果fromElement和toElement相等,则返回的集合为空。)
    返回的集合受此集合的支持,因此返回集合中的更改会反映在此集合中,反之亦然 */
    SortedSet<E> subSet(E fromElement, E toElement);
    
    /** 返回此集合中其元素严格小于toElement(不含)的部分元素集合。
    返回的集合受此集合的支持,因此返回集合中的更改会反映在此集合中,反之亦然。 */
    SortedSet<E> headSet(E toElement);

    /** 返回此集合中其元素严格大于等于fromElement(含)的部分元素集合。
    返回的集合受此集合的支持,因此返回集合中的更改会反映在此集合中,反之亦然。 */
    SortedSet<E> headSet(E fromElement);
......
}

NavigableSet

NavigableSet是继承SortedSet接口,并扩展了相应的导航方法,通过指定元素搜索目标的最接近匹配项。

......
public interface NavigableSet<E> extends SortedSet<E> {
    // 返回此集合中小于给定元素的最大元素,如果没有这样的元素,则返回null。
    E lower(E e);
    
    // 返回此集合中小于或等于给定元素的最大元素,如果没有这样的元素,则返回null。
    E floor(E e);

    // 返回此集合中大于或等于给定元素的最小元素,如果没有这样的元素,则返回null。
    E ceiling(E e);
    
    // 返回此集合中大于给定元素的最小元素,如果没有这样的元素,则返回null。
    E higher(E e);

    // 返回此集合中包含的元素的倒序集合。
    // 降序集由该集支持,因此对该集的更改会反映在降序集中,反之亦然。
    NavigableSet<E> descendingSet();

    // 按降序返回此集合中元素的迭代器
    Iterator<E> descendingIterator();
......
}

HashSet

HashSet继承AbstractSet并实现Set接口,是无序、元素不可重复、线程不安全的集合。底层使用HashMap进行实现元素的唯一,即将元素作为Map的key进行保存。

......
public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {
    
    // 底层使用HashMap实现,将元素作为map的key进行保存
    private transient HashMap<E,Object> map;

    // value值就是一个固定的Object
    private static final Object PRESENT = new Object();

    // 空参数构造方法,Map实例默认初始容量 (16) 和负载因子 (0.75)。
    // 负载因子的作用就是当key个数>=容量*0.75时就进行扩容
    public HashSet() {
        map = new HashMap<>();
    }

    // 也可以指定初始大小和负载因子
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }
    
    // default修饰的构造方法,只能同包下才有权访问
    // 而在源码注解中这样写到:构造一个新的空链接哈希集。 
    // 此包私有构造函数仅供 LinkedHashSet 使用。
    // 所以这个构造方法只是给LinkedHashSet提供的,
    // 让LinkedHashSet底层使用LinkedHashMap实现
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

    // 添加元素就是将元素作为map的key
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
......
}

TreeSet

TreeSet是继承AbstractSet并实现NavigableSet的Set集合。保留了Set集合元素不可重复的原则,且通过实现NavigableSet使得元素按照比较器进行排序。但值得注意的是TreeSet底层使用TreeMap进行实现,且元素排序也是通过TreeMap中的comparator比较器进行比较的,而TreeMap无参数构造方法默认comparator=null,所以在使用TreeSet前一定要保证所保存的元素类实现Comparable接口中compareTo(T o)方法,或者在创建TreeSet时传入Comparator比较器对象才能保证操作时对元素进行排序,所以TreeSet不允许null元素。

......
public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable {
    
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    // 创建TreeSet时传入比较器参数
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    /** 返回升序的迭代器 */
    public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

    /** 返回降序的迭代器 */
    public Iterator<E> descendingIterator() {
        return m.descendingKeySet().iterator();
    }

    /** 返回该集合的降序集合 */
    public NavigableSet<E> descendingSet() {
        return new TreeSet<>(m.descendingMap());
    }

    /** 添加元素,将元素作为map的key */
    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
......
}

LinkedHashSet

LinkedHashSet继承HashSet并实现Set接口,默认初始大小是16,创建时通过调用HashSet为其单独提供的构造方法使得LinkedHashSet底层使用LinkedHashMap实现。所以LinkedHashSet是一个有序(记录插入顺序)、不可重复、线程不安全的Set集合。

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable {

    /** 所有构造方法都是调用父类的
        HashSet(int initialCapacity, float loadFactor, boolean dummy)构造方法 */
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }

    public LinkedHashSet() {
        super(16, .75f, true);
    }

    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

    /** 其他方法均延用HashSet的实现 */    

    @Override
    public Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
    }
}

List和Set的区别

  • List有序的,按照索引(ArrayList)或者插入顺序(LinkedList)进行排序;Set可以是无序、指定排序规则进行排序(TreeSet)、插入顺序进行排序(LinkedHashSet);

  • List集合元素可重复,Set集合元素不可重复;

  • List在索引的加持下查询效率高,Set可确保元素不重复,两者适用不同场景。

Collections

Java.util.Collections是一个集合工具类,用于操作List,Set,Map等集合,并提供了一系列的静态方法,可以实现对集合元素的搜索、排序(自定义比较、混排、反转)、元素替换、复制、线程安全等操作。

/** 给定集合返回不可修改的集合方法 */
// 用给定的Collection作为参数创建UnmodifiableCollection不可修改的集合
static Collection unmodifiableCollection(Collection c);

// 用给定的List作为参数创建UnmodifiableList
// 或UnmodifiableRandomAccessList(实现RandomAccess接口的)不可修改的集合
static List unmodifiableList(List list);

// 用给定的Map作为参数创建UnmodifiableMap不可修改的Map
static Map unmodifiableMap(Map m);

// 用给定的NavigableMap作为参数创建UnmodifiableNavigableMap不可修改的NavigableMap
static NavigableMap unmodifiableNavigableMap(NavigableMap m);

// 用给定的NavigableSet作为参数创建UnmodifiableNavigableSet不可修改的NavigableSet
static NavigableSet unmodifiableNavigableSet(NavigableSet s);

// 用给定的Set作为参数创建UnmodifiableSet不可修改的Set。
static Set unmodifiableSet(Set s);

// 用给定的SortedMap作为参数创建UnmodifiableSortedMap不可修改的SortedMap。
// 底层使用Collections内部类
static SortedMap unmodifiableSortedMap(SortedMap m);

// 用给定的SortedSet作为参数创建UnmodifiableSortedSet不可修改的SortedSet
static SortedSet unmodifiableSortedSet(SortedSet s);

// 返回仅包含给定对象的不可变Set集合
static Set singleton(T o);

// 返回仅包含给定对象的不可变集合
static List singletonList(T o);

// 返回仅包含给定参数的不可变Map
static Map singletonMap(K key, V value);

/** 给定集合返回不可修改的集合方法 */
// 用给定的SortedSet创建SynchronizedSortedSet线程安全集合
static Collection synchronizedCollection(Collection c);

// 用给定的List创建SynchronizedList或SynchronizedRandomAccessList线程安全集合
static List synchronizedList(List list);

// 用给定的Map创建SynchronizedMap线程安全Map
static Map synchronizedMap(Map m);

// 用给定的NavigableMap创建SynchronizedNavigableMap线程安全NavigableMap
static NavigableMap synchronizedNavigableMap(NavigableMap m);

// 用给定的NavigableSet创建SynchronizedNavigableSet线程安全NavigableSet
static NavigableSet synchronizedNavigableSet(NavigableSet s);

// 用给定的Set创建SynchronizedSet线程安全Set
static Set synchronizedSet(Set s);

// 用给定的SortedMap创建SynchronizedSortedMap线程安全SortedMap
static SortedMap synchronizedSortedMap(SortedMap m);

// 用给定的SortedSet创建SynchronizedSortedSet线程安全SortedSet
static SortedSet synchronizedSortedSet(SortedSet s);

/** 排序 */
// 用给定列表中的元素旋转给定的距离。正数向后移动,负数向前移动,集合长度不变
static void rotate(List list, int distance);

// 根据由给定的比较器进行排序。
static void sort(List list, Comparator c);

// 交换给定列表中给定位置的元素。
static void swap(List list, int i, int j);

// 使用默认源随机性。
static void shuffle(List list);

// 使用给定的源随机排列给定的列表随机性。
static void shuffle(List list, Random rnd);

// 根据给定列表元素的自然顺序,按其升序对给定列表进行排序。元素必须实现Comparable接口
static void sort(List list);

/** 复制、替换 */
// 将所有元素从一个列表复制到另一个列表中。
static void copy(List dest, List src);

// 用给定列表的所有元素替换为给定的元素。
static void fill(List list, obj);

// 将列表中所有匹配oldVal项替换为newVal。
static boolean replaceAll(List list, oldVal, newVal);

/** 查询 */
// 返回给定对象在集合中的索引。
static int frequency(Collection c, Object o);

// 如果两个给定的集合没有相同的元素返回true
static boolean disjoint(Collection c1, Collection c2);

// 返回给定的第一个匹配项的起始位置 给定源列表中的目标列表,如果没有,则为 -1 这样的发生。
static int indexOfSubList(List source, List target);

// 返回给定 给定源列表中的目标列表,如果没有这样的目标列表,则为 -1 发生。
static int lastIndexOfSubList(List source, List target);

// 根据给定集合元素的自然顺序返回其最大元素。元素必须实现Comparable接口
static max(Collection coll);

// 返回给定集合的最大元素,根据由给定的比较器引起的阶次。
static max(Collection coll, Comparator comp);

// 根据给定集合元素的自然顺序返回其最小元素。元素必须实现Comparable接口
static min(Collection coll);

// 返回给定集合的最小元素,根据由给定的比较器引起的阶次。
static min(Collection coll, Comparator comp);
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值