Java集合框架-Collection架构

2,435 阅读6分钟

一、前言

站在巨人的肩膀上,Java集合框架系列文章参考了skywang12345——Java 集合系列,真心讲的很好,可以参考。但是不足的是,时间过于长久了,大佬的文章是基于JDK1.6.0_45,对于现在来说至少都用JDK 8.0以上了,而且JDK 6.0与JDK 8.0中集合框架的改动挺大的,所以本系列的文章是基于JDK_1.8.0_161进行说明的。

二、说明

先来看看Collection架构关系图,图片来源于Java 集合系列02之 Collection架构

从图中我们可以看到,Collection它是一个高度抽象的接口,只要分为2大分支:ListSet。并且List和Set也都是接口,它们都继承于Collection。List是一个有序的队列,可以有重复的元素;而Set是数学中的集合,它不能包含相同的元素。List和Set它们都有各自的实现类。

为了我们方便使用。JDK抽象出了AbstractCollection这个抽象类,它实现了Collection中的绝大部分函数,那么在Collection的实现类中,我们就可以通过继承AbstractCollection省去重复编码。AbstractList和AbstractSet都继承于AbstractCollection,具体的List实现类继承于AbstractList,而Set的实现类则继承于AbstractSet。

另外,Collection中有一个iterator()函数,它的作用是返回一个Iterator接口。通常,我们通过Iterator迭代器来遍历集合,ListIterator是List接口所特有的,在List接口中,通过ListIterator()返回一个ListIterator对象。接下来,我们看看各个接口和抽象类的介绍;然后,再对实现类进行详细的了解。

三、解析

1、Collection

先来看看Collection的接口定义:

public interface Collection<E> extends Iterable<E>

它是一个接口,是高度抽象出来的集合,它包含了集合的基本操作:添加、删除、清空、遍历(读取)、是否为空、获取大小、是否保护某元素等等。下面就是Collection接口的全部方法,需要说明一点的是,从JDK 8.0以后,接口中可以添加使用default或者static修饰的方法,这种方法可以有方法体,就相当于普通方法。并且通过default或者static修饰的方法就无需让子类强制重写,子类会直接继承此方法。

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);

int hashCode();

/**
 * @since 1.8
 */
@Override
default Spliterator<E> spliterator() {
	return Spliterators.spliterator(this, 0);
}

/**
 * @since 1.8
 */
default Stream<E> stream() {
	return StreamSupport.stream(spliterator(), false);
}

/**
 * @since 1.8
 */
default Stream<E> parallelStream() {
	return StreamSupport.stream(spliterator(), true);
}

源码中可以看到,从1.8开始就新增了几个默认方法。Collection接口的所有子类(直接子类和间接子类)都必须实现2种构造函数:不带参数的构造函数参数为Collection的构造函数。带参数的构造函数,可以用来转换Collection的类型。

2、List

List的接口定义:

public interface List<E> extends Collection<E>

List是继承于Collection的一个接口,即List是集合中的一种。List是有序的队列,List中的每一个元素都有一个索引;第一个元素的索引值是0,往后的元素的索引值依次+1。和Set不同,List中允许有重复的元素。

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 addAll(int index, Collection<? extends E> c);

boolean removeAll(Collection<?> c);

boolean retainAll(Collection<?> 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);
	}
}

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<E> listIterator();

ListIterator<E> listIterator(int index);

List<E> subList(int fromIndex, int toIndex);

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

既然List是继承于Collection接口,它自然就包含了Collection中的全部函数接口;由于List是有序队列,它也额外的有自己的API接口。主要有“添加、删除、获取、修改指定位置的元素”、“获取List中的子队列”等。

3、Set

Set的接口定义:

public interface Set<E> extends Collection<E>

Set是一个继承于Collection的接口,即Set也是集合中的一种。Set是没有重复元素的集合。

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 retainAll(Collection<?> c);

boolean removeAll(Collection<?> c);

void clear();

boolean equals(Object o);

int hashCode();

/**
 * @since 1.8
 */
@Override
default Spliterator<E> spliterator() {
	return Spliterators.spliterator(this, Spliterator.DISTINCT);
}

在API方面,Set的API和Collection除了JDK 1.8新增的默认方法外,其他方法都是一样的。

4、AbstractCollection

AbstractCollection的接口定义:

public abstract class AbstractCollection<E> implements Collection<E>

AbstractCollection是一个抽象类,它实现了Collection中除iterator()和size()之外的函数。AbstractCollection的主要作用:它实现了Collection接口中的大部分函数。从而方便其它类实现Collection,比如ArrayList、LinkedList等,它们这些类想要实现Collection接口,通过继承AbstractCollection就已经实现了大部分的接口了。

5、AbstractList

AbstractList的接口定义:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

AbstractList是一个继承于AbstractCollection,并且实现List接口的抽象类。它实现了List中除size()、get(int index)之外的函数。AbstractList的主要作用:它实现了List接口中的大部分函数。从而方便其它类继承List。另外,和AbstractCollection相比,AbstractList抽象类中,实现了iterator()接口。

6、AbstractSet

AbstractSet的接口定义:

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>

AbstractSet是一个继承于AbstractCollection,并且实现Set接口的抽象类。由于Set接口和Collection接口中除了JDK 1.8新增的默认方法,其他的API完全一样,Set也就没有自己单独的API。和AbstractCollection一样,它实现了List中除iterator()和size()之外的函数。AbstractSet的主要作用:它实现了Set接口中的大部分函数。从而方便其它类实现Set接口。

7、Iterator

Iterator的接口定义:

public interface Iterator<E>

Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍历集合中的元素。Iterator提供的API接口,包括:是否存在下一个元素、获取下一个元素、删除当前元素。

注意:Iterator遍历Collection时,是fail-fast机制的。即,当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。关于fail-fast的详细内容,我们会在后面专门进行说明。

boolean hasNext();

E next();

default void remove() {
	throw new UnsupportedOperationException("remove");
}

/**
 * @since 1.8
 */
default void forEachRemaining(Consumer<? super E> action) {
	Objects.requireNonNull(action);
	while (hasNext())
		action.accept(next());
}

JDK 1.8中remove()做了默认的实现,这也是和JDK 1.6不同的地方,并新增了forEachRemaining默认方法。

8、ListIterator

ListIterator的接口定义:

public interface ListIterator<E> extends Iterator<E>

ListIterator是一个继承于Iterator的接口,它是队列迭代器。专门用于便利List,能提供向前/向后遍历。相比于Iterator,它新增了添加、是否存在上一个元素、获取上一个元素等等API接口。

boolean hasNext();

E next();

boolean hasPrevious();

E previous();

int nextIndex();

int previousIndex();

void remove();

void set(E e);

void add(E e);

四、参考

Java 集合系列02之 Collection架构