Java集合总结

Java集合框架_第1张图片

List  dogs = new ArrayList();
List  dogs1 = new LinkedList();
List  dogs2 = new Vector();
List  dogs5 = new Stack();

Set  dogs3 = new HashSet();
Set  dogs4 = new TreeSet();

Queue maxHeap = new PriorityQueue();

Java集合框架_第2张图片

一、Collection

public interface Collection extends Iterable 接口和接口之间,可以使用继承关系

常用API:

Modifier and Type Method and Description
boolean add(E e)

确保此集合包含指定的元素(可选操作)。

boolean addAll(Collection c)

将指定集合中的所有元素添加到此集合(可选操作)。

void clear()

从此集合中删除所有元素(可选操作)。

boolean contains(Object o)

如果此集合包含指定的元素,则返回 true

boolean containsAll(Collection c)

如果此集合包含指定 集合中的所有元素,则返回true。

boolean equals(Object o)

将指定的对象与此集合进行比较以获得相等性。

int hashCode()

返回此集合的哈希码值。

boolean isEmpty()

如果此集合不包含元素,则返回 true

Iterator iterator()

返回此集合中的元素的迭代器。

default Stream parallelStream()

返回可能并行的 Stream与此集合作为其来源。

boolean remove(Object o)

从该集合中删除指定元素的单个实例(如果存在)(可选操作)。

boolean removeAll(Collection c)

删除指定集合中包含的所有此集合的元素(可选操作)。

default boolean removeIf(Predicate filter)

删除满足给定谓词的此集合的所有元素。

boolean retainAll(Collection c)

仅保留此集合中包含在指定集合中的元素(可选操作)。

int size()

返回此集合中的元素数。

default Spliterator spliterator()

创建一个Spliterator在这个集合中的元素。

default Stream stream()

返回以此集合作为源的顺序 Stream

Object[] toArray()

返回一个包含此集合中所有元素的数组。

 T[] toArray(T[] a)

返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。

遍历:

public class TreadTest {
	public static void main(String[] args) {
		Collection  dogs = new ArrayList();
		Dog dog = new Dog("aa");
		Dog dog2 = new Dog("bb");
		Dog dog3 = new Dog("cc");
		Dog dog4 = new Dog("dd");
		Dog dog5 = new Dog("ee");
		dogs.add(dog);          //把引用加入了集合中,不是对象
		dogs.add(dog);
	    dogs.add(dog2);
	    dogs.add(dog3);
	    dogs.add(dog4);
	    dogs.add(dog5);
	    
	    //遍历方式一
	    Iterator it = dogs.iterator();
	    while(it.hasNext()){
	    	Dog d = it.next();
	    	System.out.println(d.name);
	    }
	    //遍历方式二
	    for(Dog d : dogs){
	    	System.out.println(d.name);
	    }
	}
}

1.1. List:有序可重复

实现类有,ArrayList  LinkedList  Stack  Vector

    Vector:线程安全,但速度慢,已被ArrayList替代。

    ArrayList:线程不安全,查询速度快。

    LinkedList:链表结构,增删速度快。


取出LIst集合中元素的方式:

    get(int index):通过脚标获取元素。

    iterator():通过迭代方法获取迭代器对象。


    void add(int index, E element)  --- 在列表的指定位置插入指定元素(可选操作)。

    E get(int index)           返回列表中指定位置的元素         

    E remove(int index)       移除列表中指定位置的元素(可选操作              

    E set(int index, E element)           用指定元素替换列表中指定位置的元素(可选操作)。

1.1.1. ArrayList 

    数据结构:静态数组

    初始化大小默认为10:同样也可以设定大小:List tclass = new ArrayList(30);

构造函数源码

 /**
     * Constructs an empty list with the specified initial capacity.
     *
     */
    public ArrayList(int initialCapacity) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
    }
 
    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this(10);
    }

ArrayList 容量调整策略源码解析:

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

private void ensureCapacityInternal(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;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

ArrayListVector对比:

    ArrayList,此实现不是同步的。性能比较好,优先使用;-------方法中没有synchronized

    Vector的底层也是静态数组,但是Vector中的大量方法,都是synchronized,需要线程等待,性能比较差


1.1.2. LinkedList

    是一个双向链表类 LinkedList  --------List 接口的链接列表实现:它实现了List, Queue

    使用场景:当集合经常需要插队和移除操作时,首选LinkedList ,性能比较高

使用了链表数据结构,源码实现为:

public class LinkedList
    extends AbstractSequentialList
    implements List, Deque, Cloneable, java.io.Serializable
{
    transient int size = 0;

    transient Node first;

    transient Node last;

    public LinkedList() {
    }

    public LinkedList(Collection c) {
        this();
        addAll(c);
    }

    private void linkFirst(E e) {
        final Node f = first;
        final Node newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
        size++;
        modCount++;
    }

    void linkLast(E e) {
        final Node l = last;
        final Node newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
        size++;
        modCount++;
    }

    void linkBefore(E e, Node succ) {
        // assert succ != null;
        final Node pred = succ.prev;
        final Node newNode = new Node<>(pred, e, succ);
        succ.prev = newNode;
        if (pred == null)
            first = newNode;
        else
            pred.next = newNode;
        size++;
        modCount++;
    }

    private E unlinkFirst(Node f) {
        // assert f == first && f != null;
        final E element = f.item;
        final Node next = f.next;
        f.item = null;
        f.next = null; // help GC
        first = next;
        if (next == null)
            last = null;
        else
            next.prev = null;
        size--;
        modCount++;
        return element;
    }

    private E unlinkLast(Node l) {
        // assert l == last && l != null;
        final E element = l.item;
        final Node prev = l.prev;
        l.item = null;
        l.prev = null; // help GC
        last = prev;
        if (prev == null)
            first = null;
        else
            prev.next = null;
        size--;
        modCount++;
        return element;
    }

    E unlink(Node x) {
        // assert x != null;
        final E element = x.item;
        final Node next = x.next;
        final Node prev = x.prev;

        if (prev == null) {
            first = next;
        } else {
            prev.next = next;
            x.prev = null;
        }

        if (next == null) {
            last = prev;
        } else {
            next.prev = prev;
            x.next = null;
        }

        x.item = null;
        size--;
        modCount++;
        return element;
    }

常用API:

Modifier and Type Method and Description
boolean add(E e)

将指定的元素追加到此列表的末尾。

void add(int index, E element)

在此列表中的指定位置插入指定的元素。

boolean addAll(Collection c)

按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾。

boolean addAll(int index, Collection c)

将指定集合中的所有元素插入到此列表中,从指定的位置开始。

void addFirst(E e)

在该列表开头插入指定的元素。

void addLast(E e)

将指定的元素追加到此列表的末尾。

void clear()

从列表中删除所有元素。

Object clone()

返回此 LinkedList的浅版本。

boolean contains(Object o)

如果此列表包含指定的元素,则返回 true

E element()

检索但不删除此列表的头(第一个元素)。

E get(int index)

返回此列表中指定位置的元素。

E getFirst()

返回此列表中的第一个元素。

E getLast()

返回此列表中的最后一个元素。

int indexOf(Object o)

返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。

int lastIndexOf(Object o)

返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。

ListIterator listIterator(int index)

从列表中的指定位置开始,返回此列表中元素的列表迭代器(按适当的顺序)。

boolean offer(E e)

将指定的元素添加为此列表的尾部(最后一个元素)。

boolean offerFirst(E e)

在此列表的前面插入指定的元素。

boolean offerLast(E e)

在该列表的末尾插入指定的元素。

E peek()

检索但不删除此列表的头(第一个元素)。

E peekFirst()

检索但不删除此列表的第一个元素,如果此列表为空,则返回 null

E peekLast()

检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null

E poll()

检索并删除此列表的头(第一个元素)。

E pollFirst()

检索并删除此列表的第一个元素,如果此列表为空,则返回 null

E pollLast()

检索并删除此列表的最后一个元素,如果此列表为空,则返回 null

E pop()

从此列表表示的堆栈中弹出一个元素。

void push(E e)

将元素推送到由此列表表示的堆栈上。

E remove()

检索并删除此列表的头(第一个元素)。

E remove(int index)

删除该列表中指定位置的元素。

boolean remove(Object o)

从列表中删除指定元素的第一个出现(如果存在)。

E removeFirst()

从此列表中删除并返回第一个元素。

boolean removeFirstOccurrence(Object o)

删除此列表中指定元素的第一个出现(从头到尾遍历列表时)。

E removeLast()

从此列表中删除并返回最后一个元素。

boolean removeLastOccurrence(Object o)

删除此列表中指定元素的最后一次出现(从头到尾遍历列表时)。

E set(int index, E element)

用指定的元素替换此列表中指定位置的元素。

int size()

返回此列表中的元素数。

Spliterator spliterator()

在此列表中的元素上创建late-binding故障快速 Spliterator

Object[] toArray()

以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。

 T[] toArray(T[] a)

以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。


1.1.3. Stack

Stack 类表示后进先出(LIFO)的对象堆栈                  

典型应用场景: XMLSAX解析模式

public
class Stack extends Vector {
    
    public Stack() {
    }

常用方法:

Modifier and Type Method and Description
boolean empty()

测试此堆栈是否为空。

E peek()

查看此堆栈顶部的对象,而不从堆栈中删除它。

E pop()

删除此堆栈顶部的对象,并将该对象作为此函数的值返回。

E push(E item)

将项目推送到此堆栈的顶部。

int search(Object o)

返回一个对象在此堆栈上的基于1的位置。 


1.2. Set:不可重复,无序

HashSet:线程不安全,存取速度快。

    通过equals方法和hashCode 方法来保证元素的唯一性。

TreeSet:线程不安全,可以对Set集合中的元素进行排序。

    通过compareTo或者compare 方法中的来保证元素的唯一性。元素是以二叉树的形式存 放的。


1.2.1HashSet

源码:实际上是一个 HashMap 实例

public class HashSet
    extends AbstractSet
    implements Set, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap map;

    private static final Object PRESENT = new Object();

    public HashSet() {
        map = new HashMap<>();
    }

    public HashSet(Collection c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

    public Iterator iterator() {
        return map.keySet().iterator();
    }
Modifier and Type Method and Description
boolean add(E e)

将指定的元素添加到此集合(如果尚未存在)。

void clear()

从此集合中删除所有元素。

Object clone()

返回此 HashSet实例的浅层副本:元素本身不被克隆。

boolean contains(Object o)

如果此集合包含指定的元素,则返回 true

boolean isEmpty()

如果此集合不包含元素,则返回 true

Iterator iterator()

返回此集合中元素的迭代器。

boolean remove(Object o)

如果存在,则从该集合中删除指定的元素。

int size()

返回此集合中的元素数(其基数)。

Spliterator spliterator()

在此集合中的元素上创建late-binding故障快速 Spliterator

1.2.2. TreeSet

public class TreeSet extends AbstractSet
    implements NavigableSet, Cloneable, java.io.Serializable
{
    
    private transient NavigableMap m;

    private static final Object PRESENT = new Object();

    TreeSet(NavigableMap m) {
        this.m = m;
    }

    public TreeSet() {
        this(new TreeMap());
    }

    public TreeSet(Comparator comparator) {
        this(new TreeMap<>(comparator));
    }

    public TreeSet(Collection c) {
        this();
        addAll(c);
    }

    public TreeSet(SortedSet s) {
        this(s.comparator());
        addAll(s);
    }

    public Iterator iterator() {
        return m.navigableKeySet().iterator();
    }


1.2. Queue

Java集合框架_第3张图片

public interface Queue extends Collection
Modifier and Type Method and Description
boolean add(E e)

将指定的元素插入到此队列中,如果可以立即执行此操作,而不会违反容量限制, true在成功后返回 IllegalStateException如果当前没有可用空间,则抛出IllegalStateException。

E element()

检索,但不删除,这个队列的头。

boolean offer(E e)

如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。

E peek()

检索但不删除此队列的头,如果此队列为空,则返回 null

E poll()

检索并删除此队列的头,如果此队列为空,则返回 null

E remove()

检索并删除此队列的头。 


下面是queue的应用:

BlockingQueue

A线程可以知道b线程的存在

是一个接口并非一个具体实现:

ArrayBlockingQueue

ArrayBlockingQueue的内部元素都放置在一个对象数组中:final Object[] items;

Offer():当队列已经满了,会立即返回false

Put():如果队列满了会一直等待

Pool():弹出元素,如果为空返回null

Take():弹出元素,如果为空等待到有元素即可。

Take方法:

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }
    
private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }


Put方法:

public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }
/**
     * Extracts element at current take position, advances, and signals.
     * Call only when holding lock.
     */
    private E extract() {
        final Object[] items = this.items;
        E x = this.cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }

LinkedBlockingQueue(锁分离)

两把不同的锁
/** Lock held by take, poll, etc */
    private final ReentrantLock takeLock = new ReentrantLock();
 
    /** Wait queue for waiting takes */
    private final Condition notEmpty = takeLock.newCondition();
 
    /** Lock held by put, offer, etc */
    private final ReentrantLock putLock = new ReentrantLock();
 
    /** Wait queue for waiting puts */
    private final Condition notFull = putLock.newCondition();
 
Take函数
public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();//不能有两个线程同时取数据
        try {
            while (count.get() == 0) {//如果没有数据,一直等待(因为是lockInterruptibly,可中断)
                notEmpty.await();
            }
            x = dequeue();//取得第一个数据
            c = count.getAndDecrement();//数量-1,原子操作,因为会和put同时访问count。
            if (c > 1)
                notEmpty.signal();//通知其他take操作
        } finally {
            takeLock.unlock();//释放锁
        }
        if (c == capacity)
            signalNotFull();//通知put操作,已有空余空间
        return x;
    }
 
Put函数
public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        // Note: convention in all put/take/etc is to preset local var
        // holding count negative to indicate failure unless set.
        int c = -1;
        Node node = new Node(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();//上锁不能有两个线程同时进行put函数
        try {
            /*
             * Note that count is used in wait guard even though it is
             * not protected by lock. This works because count can
             * only decrease at this point (all other puts are shut
             * out by lock), and we (or some other waiting put) are
             * signalled if it ever changes from capacity. Similarly
             * for all other uses of count in other wait guards.
             */
            while (count.get() == capacity) {//当队列已经满了以后,等待
                notFull.await();
            }
            enqueue(node);//插入数据
            c = count.getAndIncrement();//更新总数
            if (c + 1 < capacity)
                notFull.signal();//有足够的空间,通知其他线程
        } finally {
            putLock.unlock();//释放锁
        }
        if (c == 0)
            signalNotEmpty();//释放成功后,通知take函数取数据
    }

并发下的ArrayList

当ArrayList在扩容的时候,内部一致性被破坏,由于没有锁的保护,另外一个线程访问不到不一致的内部状态,导致出现越界问题。

还会出现多个线程同时对同一位置进行赋值。

concurrentlinkedqueue

concurrentlinkedqueue:

高并发环境中可以说是最好的队列,也可以看做是一个线程安全的linkedList。

CopyOnWriteArrayList

性能很好的读写list,在读写的时候任何时候都不加锁;只有在写写的时候需要同步等待。

当写操作的时候,进行一次自我复制。对原有的数据进行一次复制,将修改的内容写入副本修改完之后,将副本替换原来的数据。


PriorityQueue

    PriorityQueue也叫优先队列,所谓优先队列指的就是每次从优先队列中取出来的元素要么是最大值(最大堆),要么是最小值(最小堆)。我们知道,队列是一种先进先出的数据结构,每次从队头出队(移走一个元素),从队尾插入一个元素(入队)。

boolean add(E e)

将指定的元素插入到此优先级队列中。

void clear()

从此优先级队列中删除所有元素。

Comparator comparator()

返回用于为了在这个队列中的元素,或比较null如果此队列根据所述排序natural ordering的元素。

boolean contains(Object o)

如果此队列包含指定的元素,则返回 true

Iterator iterator()

返回此队列中的元素的迭代器。

boolean offer(E e)

将指定的元素插入到此优先级队列中。

E peek()

检索但不删除此队列的头,如果此队列为空,则返回 null

E poll()

检索并删除此队列的头,如果此队列为空,则返回 null

boolean remove(Object o)

从该队列中删除指定元素的单个实例(如果存在)。

int size()

返回此集合中的元素数。

Spliterator spliterator()

在此队列中的元素上创建late-binding失败快速 Spliterator

Object[] toArray()

返回一个包含此队列中所有元素的数组。

 T[] toArray(T[] a)

返回一个包含此队列中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。


ArrayDeque(一种双端队列)

参考:http://blog.csdn.net/qq_35326718/article/details/72972159

常用api方法:

boolean add(E e)

在此deque的末尾插入指定的元素。

void addFirst(E e)

在此deque前面插入指定的元素。

void addLast(E e)

在此deque的末尾插入指定的元素。

void clear()

从这个deque中删除所有的元素。 

E element()

检索,但不删除,由这个deque表示的队列的头。

E getFirst()

检索,但不删除,这个deque的第一个元素。

E getLast()

检索,但不删除,这个deque的最后一个元素。

boolean isEmpty()

如果此deque不包含元素,则返回 true

Iterator iterator()

返回此deque中的元素的迭代器。

boolean offer(E e)

在此deque的末尾插入指定的元素。

boolean offerFirst(E e)

在此deque前面插入指定的元素。

boolean offerLast(E e)

在此deque的末尾插入指定的元素。

E peek()

检索但不删除由此deque表示的队列的头部,如果此deque为空,则返回 null

E peekFirst()

检索但不删除此deque的第一个元素,如果此deque为空,则返回 null

E peekLast()

检索但不删除此deque的最后一个元素,或返回 null如果此deque为空)。

E poll()

检索并删除由此deque(换句话说,该deque的第一个元素)表示的队列的 null如果此deque为空,则返回 null

E pollFirst()

检索并删除此deque的第一个元素,如果此deque为空,则返回 null

E pollLast()

检索并删除此deque的最后一个元素,如果此deque为空,则返回 null

E pop()

从这个deque表示的堆栈中弹出一个元素。

void push(E e)

将元素推送到由此deque表示的堆栈上。

E remove()

检索并删除由此deque表示的队列的头部。

boolean remove(Object o)

从此deque中删除指定元素的单个实例。

E removeFirst()

检索并删除此deque的第一个元素。

boolean removeFirstOccurrence(Object o)

删除此deque中指定元素的第一个出现(从头到尾遍历deque时)。

E removeLast()

检索并删除此deque的最后一个元素。

boolean removeLastOccurrence(Object o)

删除此deque中指定元素的最后一次(从头到尾遍历deque时)。

int size()

返回此deque中的元素数。

Spliterator spliterator()

创建一个late-binding失败快速 Spliterator在这个deque的元素。

Object[] toArray()

以适当的顺序返回一个包含此deque中所有元素的数组(从第一个到最后一个元素)。

 T[] toArray(T[] a)

以正确的顺序返回一个包含此deque中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。