Java集合总结
Listdogs = 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 ();
一、Collection
public interface Collection
常用API:
Modifier and Type | Method and Description |
---|---|
boolean |
add(E e) 确保此集合包含指定的元素(可选操作)。 |
boolean |
addAll(Collection extends E> 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() 返回可能并行的 |
boolean |
remove(Object o) 从该集合中删除指定元素的单个实例(如果存在)(可选操作)。 |
boolean |
removeAll(Collection> c) 删除指定集合中包含的所有此集合的元素(可选操作)。 |
default boolean |
removeIf(Predicate super E> filter) 删除满足给定谓词的此集合的所有元素。 |
boolean |
retainAll(Collection> c) 仅保留此集合中包含在指定集合中的元素(可选操作)。 |
int |
size() 返回此集合中的元素数。 |
default Spliterator |
spliterator() 创建一个 |
default Stream |
stream() 返回以此集合作为源的顺序 |
Object[] |
toArray() 返回一个包含此集合中所有元素的数组。 |
|
toArray(T[] a) 返回包含此集合中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。 |
遍历:
public class TreadTest { public static void main(String[] args) { Collectiondogs = 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
构造函数源码
/** * 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); }
ArrayList与Vector对比:
ArrayList,此实现不是同步的。性能比较好,优先使用;-------方法中没有synchronized
Vector的底层也是静态数组,但是Vector中的大量方法,都是synchronized,需要线程等待,性能比较差
1.1.2. LinkedList
是一个双向链表类 LinkedList
使用场景:当集合经常需要插队和移除操作时,首选LinkedList
使用了链表数据结构,源码实现为:
public class LinkedListextends AbstractSequentialList implements List , Deque , Cloneable, java.io.Serializable { transient int size = 0; transient Node first; transient Node last; public LinkedList() { } public LinkedList(Collection extends E> 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 extends E> c) 按照指定集合的迭代器返回的顺序将指定集合中的所有元素追加到此列表的末尾。 |
boolean |
addAll(int index, Collection extends E> c) 将指定集合中的所有元素插入到此列表中,从指定的位置开始。 |
void |
addFirst(E e) 在该列表开头插入指定的元素。 |
void |
addLast(E e) 将指定的元素追加到此列表的末尾。 |
void |
clear() 从列表中删除所有元素。 |
Object |
clone() 返回此 |
boolean |
contains(Object o) 如果此列表包含指定的元素,则返回 |
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() 检索但不删除此列表的第一个元素,如果此列表为空,则返回 |
E |
peekLast() 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 |
E |
poll() 检索并删除此列表的头(第一个元素)。 |
E |
pollFirst() 检索并删除此列表的第一个元素,如果此列表为空,则返回 |
E |
pollLast() 检索并删除此列表的最后一个元素,如果此列表为空,则返回 |
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和故障快速 |
Object[] |
toArray() 以正确的顺序(从第一个到最后一个元素)返回一个包含此列表中所有元素的数组。 |
|
toArray(T[] a) 以正确的顺序返回一个包含此列表中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。 |
1.1.3. Stack
Stack 类表示后进先出(LIFO)的对象堆栈
典型应用场景: XML的SAX解析模式
public class Stackextends 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.1. HashSet
源码:实际上是一个 HashMap 实例
public class HashSetextends 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 extends E> 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和故障快速 |
1.2.2. TreeSet
public class TreeSetextends 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 super E> comparator) { this(new TreeMap<>(comparator)); } public TreeSet(Collection extends E> c) { this(); addAll(c); } public TreeSet(SortedSet s) { this(s.comparator()); addAll(s); } public Iterator iterator() { return m.navigableKeySet().iterator(); }
1.2. Queue
public interface Queueextends Collection
Modifier and Type | Method and Description |
---|---|
boolean |
add(E e) 将指定的元素插入到此队列中,如果可以立即执行此操作,而不会违反容量限制, |
E |
element() 检索,但不删除,这个队列的头。 |
boolean |
offer(E e) 如果在不违反容量限制的情况下立即执行,则将指定的元素插入到此队列中。 |
E |
peek() 检索但不删除此队列的头,如果此队列为空,则返回 |
E |
poll() 检索并删除此队列的头,如果此队列为空,则返回 |
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; Nodenode = 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 super E> |
comparator() 返回用于为了在这个队列中的元素,或比较 |
boolean |
contains(Object o) 如果此队列包含指定的元素,则返回 |
Iterator |
iterator() 返回此队列中的元素的迭代器。 |
boolean |
offer(E e) 将指定的元素插入到此优先级队列中。 |
E |
peek() 检索但不删除此队列的头,如果此队列为空,则返回 |
E |
poll() 检索并删除此队列的头,如果此队列为空,则返回 |
boolean |
remove(Object o) 从该队列中删除指定元素的单个实例(如果存在)。 |
int |
size() 返回此集合中的元素数。 |
Spliterator |
spliterator() 在此队列中的元素上创建late-binding和失败快速 |
Object[] |
toArray() 返回一个包含此队列中所有元素的数组。 |
|
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不包含元素,则返回 |
Iterator |
iterator() 返回此deque中的元素的迭代器。 |
boolean |
offer(E e) 在此deque的末尾插入指定的元素。 |
boolean |
offerFirst(E e) 在此deque前面插入指定的元素。 |
boolean |
offerLast(E e) 在此deque的末尾插入指定的元素。 |
E |
peek() 检索但不删除由此deque表示的队列的头部,如果此deque为空,则返回 |
E |
peekFirst() 检索但不删除此deque的第一个元素,如果此deque为空,则返回 |
E |
peekLast() 检索但不删除此deque的最后一个元素,或返回 |
E |
poll() 检索并删除由此deque(换句话说,该deque的第一个元素)表示的队列的 |
E |
pollFirst() 检索并删除此deque的第一个元素,如果此deque为空,则返回 |
E |
pollLast() 检索并删除此deque的最后一个元素,如果此deque为空,则返回 |
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和失败快速 |
Object[] |
toArray() 以适当的顺序返回一个包含此deque中所有元素的数组(从第一个到最后一个元素)。 |
|
toArray(T[] a) 以正确的顺序返回一个包含此deque中所有元素的数组(从第一个到最后一个元素); 返回的数组的运行时类型是指定数组的运行时类型。 |