单列集合的父类,在jdk1.8时新增了方法:
public interface Collection<E> extends Iterable<E> {
// Query Operations
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
boolean add(E e);
boolean remove(Object o);
// Bulk Operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
// 按照一定规则过滤集合中的元素
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();
// Comparison and hashing
boolean equals(Object o);
int hashCode();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
}
测试:
// removeIf:过滤集合,有过滤返回true,无变化返回false。
private static void testRemoveIf() {
List<String> strings = new ArrayList<>();
strings.add("a");
strings.add("");
strings.add("b");
System.out.println(Arrays.toString(strings.toArray())); // [a, , b]
// 等价于 strings = strings.stream().filter(str -> !str.isEmpty()).collect(Collectors.toList());
// 起到过滤作用
strings.removeIf(String::isEmpty); // true
System.out.println(Arrays.toString(strings.toArray())); // [a, b]
}
// containAll:取交集后赋给调用者,有变化返回true,无变化返回false。
private static void testRetainAll() {
List<String> list1 = new ArrayList<>();
list1.add("a");
list1.add("b");
list1.add("c");
list1.add("d");
List<String> list2 = new ArrayList<>();
list2.add("a");
list2.add("b");
list2.add("c");
list2.add("d");
List<String> list3 = new ArrayList<>();
list3.add("a");
list3.add("b");
list3.add("c");
list3.add("e");
// list1与list2做交集,结果集与list2做比较,如果相同返回true,否则返回false
System.out.println("containAll:" + list1.containsAll(list2)); // containAll:true
// retain是保留的意思,list1与list2做交集,结果集赋值给list1,如果list1被改变返回true,否则返回false
System.out.println("retainAll:" + list1.retainAll(list2)); // retainAll:false
System.out.println("retainAll:" + list1.retainAll(list3)); // retainAll:true
System.out.println("list1:" + list1); // list1:[a, b, c]
System.out.println("list2:" + list2); // list2:[a, b, c, d]
System.out.println("list3:" + list3); // list2:[a, b, c, e]
}
// 是一个并行执行的流,提高你的多线程任务的速度。
// 展示顺序不一定会是1、2、3、4、5、6、7、8、9,而可能是任意的顺序
private static void testParallelStream() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(out::println);
}
AbstractCollection 是Java集合框架中Collection接口的一个直接实现类,Collection下的大多数子类都继承AbstractCollection,比如 List 的实现类, Set的实现类。
AbstractCollection抽象类中已经实现了Collection中大部分接口,但是需要子类重写其抽象方法:
public abstract class AbstractCollection<E> implements Collection<E> {
protected AbstractCollection() {
}
// Query Operations
// 需要子类自行重写
public abstract Iterator<E> iterator();
public abstract int size();
public boolean isEmpty() {
return size() == 0;
}
// 这里对null作了特别的处理
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
public Object[] toArray() {
// Estimate size of array; be prepared to see more or fewer elements
Object[] r = new Object[size()];
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) // fewer elements than expected
return Arrays.copyOf(r, i);
r[i] = it.next();
}
return it.hasNext() ? finishToArray(r, it) : r;
}
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected
if (a == r) {
r[i] = null; // null-terminate
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
@SuppressWarnings("unchecked")
private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
int i = r.length;
while (it.hasNext()) {
int cap = r.length;
if (i == cap) {
int newCap = cap + (cap >> 1) + 1;
// overflow-conscious code
if (newCap - MAX_ARRAY_SIZE > 0)
newCap = hugeCapacity(cap + 1);
r = Arrays.copyOf(r, newCap);
}
r[i++] = (T)it.next();
}
// trim if overallocated
return (i == r.length) ? r : Arrays.copyOf(r, i);
}
private static int hugeCapacity(int minCapacity) {
if (minCapacity < 0) // overflow
throw new OutOfMemoryError
("Required array size too large");
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;
}
// Modification Operations
// 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) {
it.remove();
return true;
}
}
} else {
while (it.hasNext()) {
if (o.equals(it.next())) {
it.remove();
return true;
}
}
}
return false;
}
// Bulk Operations
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<?> it = iterator();
while (it.hasNext()) {
if (c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<E> it = iterator();
while (it.hasNext()) {
if (!c.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
public void clear() {
Iterator<E> it = iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
}
// String conversion
public String toString() {
Iterator<E> it = iterator();
if (! it.hasNext())
return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (! it.hasNext())
return sb.append(']').toString();
sb.append(',').append(' ');
}
}
}
List的特点:有序、可重复、元素为可空。
List的实现类:ArrayList、LinkedList、Vector。(子抽象类AbstractList)
ArrayList:底层由数组实现,允许元素随机访问,但是向 ArrayList 列表中间插入删除元素需要移位复制速度略慢。
LinkList:底层由双向链表实现,适合频繁向列表中插入删除元素,随机访问需要遍历所以速度略慢,适合当做堆栈、队列、双向队列使用。
Vector:实现原理和ArrayList几乎是相同的,线程安全。
public interface List<E> extends Collection<E> {
// Query Operations
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
boolean add(E e);
boolean remove(Object o);
// Bulk Modification Operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
//指定索引位置插入(在ArrayList和LinkedList中具体实现完全不同)
boolean addAll(int index, Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
// 具体使用将案例
@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);
}
}
void clear();
// Comparison and hashing
boolean equals(Object o);
int hashCode();
// Positional Access Operations
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
// Search Operations
int indexOf(Object o);
int lastIndexOf(Object o);
// List Iterators
ListIterator<E> listIterator();
ListIterator<E> listIterator(int index);
// View
List<E> subList(int fromIndex, int toIndex);
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.ORDERED);
}
}
// 排序
private static void testSort() {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(5);
arrayList.add(4);
arrayList.add(3);
arrayList.add(2);
arrayList.add(1);
// 等价于:arrayList.sort(Integer::compareTo);
arrayList.sort((o1, o2) -> o1.compareTo(o2));
out.println(Arrays.toString(arrayList.toArray())); // [1, 2, 3, 4, 5]
}
ListIterator listIterator();
ListIterator listIterator(int index);
详见:
《迭代器(Iterable+Iterator+ListIterator+Enumeration)详解》
List subList(int fromIndex, int toIndex);
此方法并没有创建一个新的 List,然后把旧List的指定范围子元素拷贝进新List中去。
而是subList返回的是List原来的引用,只不过把开始位置 offset 和 size 改了。
AbstractList中的部分源码:
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public List<E> subList(int fromIndex, int toIndex) {
return (this instanceof RandomAccess ?
new RandomAccessSubList<>(this, fromIndex, toIndex) :
new SubList<>(this, fromIndex, toIndex));
}
}
class SubList<E> extends AbstractList<E> {
private final AbstractList<E> l;
private final int offset;
private int size;
SubList(AbstractList<E> list, int fromIndex, int toIndex) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > list.size())
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
l = list;
offset = fromIndex;
size = toIndex - fromIndex;
this.modCount = l.modCount;
}
}
测试:
private static void testSubList() {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("a");
arrayList.add("b");
arrayList.add("c");
arrayList.add("d");
List<String> subList = arrayList.subList(0, 2); // 包头不包尾
out.println(Arrays.toString(subList.toArray())); // [a, b]
out.println(Arrays.toString(arrayList.toArray())); // [a, b, c, d]
// 对截取后的集合操作
subList.remove(0);
out.println(Arrays.toString(subList.toArray())); // [b]
out.println(Arrays.toString(arrayList.toArray())); // [b, c, d]
}
结论:由于subList持有List同一个引用,所以对subList进行的操作也会影响到原有的List。
Set的特点:无序、不可重复、元素为可空。
Set的实现类:HashSet、LinkHashSet(有序)、TreeSet。(子抽象类AbstractSet)
HashSet:是为快速查找元素而设计,存入 HashSet 的元素必须定义 hashCode 方法,其实质可以理解为是 HashMap 的包装类,所以 HashSet 的值还具备可 null 性;
LinkedHashSet:具备 HashSet 的查找速度且通过链表保证了元素的插入顺序(实质为 HashSet 的子类),迭代时是有序的,同理存入 LinkHashSet 的元素必须定义 hashCode 方法;
TreeSet:实质是 TreeMap 的包装类,所以 TreeSet 的值不备可 null 性,其保证了元素的有序性,底层为红黑树结构,存入TreeSet 的元素必须实现 Comparable 接口;不过特别注意 EnumSet 的实现和 EnumMap 没有一点关系。
Set的所有方法都是继承于Collection,所以源码没啥好看的。
public interface Set<E> extends Collection<E> {
// Query Operations
int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
// Modification Operations
boolean add(E e);
boolean remove(Object o);
// Bulk Operations
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean retainAll(Collection<?> c);
boolean removeAll(Collection<?> c);
void clear();
// Comparison and hashing
boolean equals(Object o);
int hashCode();
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT);
}
}
Queue的特点:队列。
Queue 用来存放等待处理元素的集合,这种场景一般用于缓冲、并发访问。
支持 FIFO(first in first out)。
Queue的实现类:LinkedList、PriorityQueue。子接口:Deque
LinkedList:保证了按照元素的插入顺序进行操作;
PriorityQueue:按照优先级进行插入抽取操作,元素可以通过实现 Comparable 接口来保证优先顺序。
Deque:表示更为通用的双端队列,有明确的在头或尾进行查看、添加和删除的方法。
public interface Queue<E> extends Collection<E> {
// 尾部添加,在添加失败(比如队列已满)时会报一些运行时错误。
boolean add(E e);
// 尾部添加,在添加失败时也不会奔溃,只会返回 false。
boolean offer(E e);
// 删除并返回头部,当队列为空时会报NoSuchElementException。
E remove();
// 删除并返回头部,当队列为空时不会奔溃,只会返回 null。
E poll();
// 获取但不删除,当队列为空时抛出异常。
E element();
// 获取但不删除,当队列为空时返回null。
E peek();
}
测试:
private static void testQueue() {
Queue<String> linkedList = new LinkedList<>();
// out.println(linkedList.poll()); // null
// linkedList.remove(); // java.util.NoSuchElementException
// out.println(linkedList.peek()); // null
// linkedList.element(); // java.util.NoSuchElementException
linkedList.add("a");
linkedList.add("b");
linkedList.offer("c");
linkedList.offer("d");
// out.println(linkedList.remove()); // a
}