这里写目录标题
前言
最近开始学习一些源码,netty、spring、springboot都在计划内,先从jdk源码开始吧。jdk版本为14。
类图
Iterable
* Implementing this interface allows an object to be the target of the enhanced
* {@code for} statement (sometimes called the "for-each loop" statement).
*
/**
* Returns an iterator over elements of type {@code T}.
* 返回T类型的迭代器
* @return an Iterator.
*/
Iterator<T> iterator();
// 对每个元素进行消费,直到所有元素被消费完,或者消费过程中抛出了异常,消费的顺序和迭代的顺序相同
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
最后一个 spliterator比较陌生,Spliterator就是用来切分元素的,是一个可分割的迭代器,就是可以将Spilterator实例分割成多个小的Spilterator实例。
这个类在利用集合获取数组流的时候会用到,比如parallelStream()。因为使用并行去遍历时,数据会被分成多个段。
Collection
方法如上,这里只挑选几个来看。
Collection.toArray()
Object[] toArray();
返回含有集合中所有元素的数组,返回的是一个Object[]。值得注意的一点是返回的数组是“安全的”,并且没有任何指向集合中维护的数组,即使集合中含有这个数组,也要new一个数组并返回,文档原文如下:
*the returned array will be "safe" in that no references to it are
* maintained by this collection. (In other words, this method must
* allocate a new array even if this collection is backed by an array).
* The caller is thus free to modify the returned array.
Collection.toArray(T[] a)
toArray(T[] a);
<T> T[] toArray(T[] a);
如果传入的数组是合适的,就将所有元素复制到这个数组返回,否则将集合所有元素复制到一个新的数组并返回。文档原文如下:
* Returns an array containing all of the elements in this collection;
* the runtime type of the returned array is that of the specified array.
* If the collection fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this collection.
Collection.toArray(IntFunction<T[]> generator)
default <T> T[] toArray(IntFunction<T[]> generator) {
return toArray(generator.apply(0));
}
用指定的IntFunction创建数组,并调用前面的Collection.toArray(T[] a)方法,这里并没用使用IntFunction真正创建数组,因为apply的参数为0。
* Returns an array containing all of the elements in this collection,
* using the provided {@code generator} function to allocate the returned array.
示例:
String[] y = x.toArray(String[]::new)
可以看到,三种toArray方法中这种是最优雅的。
Collection.removeIf
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;
}
删除集合中所有符合条件的元素,如果该迭代器不支持删除操作则在遇到第一个符合删除条件的时候抛出UnsupportedOperationException。
Collection.Stream
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
以集合作为数据源产生流。简单说下流的概念,其实就是字面意思,数据流,并行流就是将source切分成几个部分,多条管道。
Collection.parallelStream
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
产生并行流。
Collection接口 就分析到这。接下来分析List接口。
List
类图
下面挑选几个来分析。
List.replaceAll
default void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
final ListIterator<E> li = this.listIterator();
while (li.hasNext()) {
li.set(operator.apply(li.next()));
}
}
使用迭代器遍历集合并替换每一个元素。
示例
List<Integer> list = Arrays.asList( 1, 2, 3, 4, 5, 6);
list.replaceAll(integer -> integer*2);
list.forEach(System.out::println);
List.sort
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);
}
}
传入比较器,先获取集合对应的数组,将数组排序后在用迭代器将集合的所有元素替换为排好序的数组的所有元素。
List.copyOf
static <E> List<E> copyOf(Collection<? extends E> coll) {
return ImmutableCollections.listCopy(coll);
}
是一个静态方法,将集合coll的所有元素复制到一个不可变集合并返回。
List接口就分析到这。
HashSet
类图
继承关系是非常清晰的,两个抽象类就是模板方法设计模式的体现,她们提供了一些通用方法的实现。为了更清楚的说明这一点,下面贴上这两个抽象类的一些方法的信息。
成员变量
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object();
因为HashSet内部维护了一个HashMap,基本上所有对HashSet的操作内部都依赖于这个HashMap;PRESENT是一个哑的变量,用于对HashMap操作的时候作为value使用。
构造函数
无参构造函数
/**
* Constructs a new, empty set; the backing {@code HashMap} instance has
* default initial capacity (16) and load factor (0.75). 初始时容量为16,平衡因子为0.75
*/
public HashSet() {
map = new HashMap<>();
}
无参构造函数仅仅做了一件事:初始化一个 HashMap<>(),从而可知 HashSet内部维护了一个 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);
}
- 传入一个集合:初始化HashMap的容量为c.size()/.75f 和 16的较大值
- 传入指定的初始容量和负载因子
- 指定初始容量
由于HashSet是基于HashMap的,所有接下来就来看HashMap。