JDK9 开始,java.util 包作为 java.base 模块的一部分。

概述

集合框架的设计目标

  1. 高性能。
  2. 不同类型的集合使用方式相似,有很好的互操作性。
  3. 容易扩展或适配集合。

Iterator 接口提供了访问集合中元素通用、标准化的方式。任意集合类都可以使用 Iterator 提供的方法访问元素。

JDK8 提供了 spliterator 类型迭代器,它支持并发迭代。Spliterator 接口支持 spliterator 迭代器。若干个内嵌接口支持原始类型,比如 PrimitiveIterator 和 PrimitiveIterator.OfDouble。

框架也定义了若干个 map 接口和类,map 以键值对的方式存储元素。

集合接口

接口 描述
Collection 允许处理一批元素,位于集合层次的顶层
List 扩展了 Collection 处理顺序元素
Queue 扩展了 Collection,从头部移除元素
Deque 扩展了 Queue,双端队列
Set 扩展了 Collection,元素必须唯一
SortedSet 扩展了 Set
NavigableSet 扩展了 SortedSet,基于最接近匹配搜索元素

集合也使用了 ComparatorRandomAccessIteratorListIteratorSpliterator 接口。分别定义了两个对象如何比较、支持随机访问元素和遍历集合中的元素的功能。

提供修改元素方法的集合称为可修改的(modifiable),不提供的集合称为不可修改的(unmodifiable)。所有内建集合都是可修改的。

定义集合的类必须实现 Collection 接口,它的形式为

interface Collection<E>

Collection 扩展了 Iterable 接口,所以可以使用 for-each 语句遍历集合中的元素。

add() 方法向集合中添加一个元素,addAll() 方法向集合中添加另一个集合的所有元素。

remove() 方法用于移除一个元素,removeAll() 方法用于移除一批元素,retainAll() 方法移除不在参数中的所有元素,removeIf() 方法满足某条件时移除元素,clear() 方法清空集合。

contains() 方法判断集合中某元素是否存在,containsAll() 方法判断集合中作为参数的另一个集合中所有元素是否都存在,isEmpty() 方法判断集合是否为空,size() 方法返回集合中当前元素个数。

toArray() 方法不使用参数时返回集合中所有元素构成的数组,数组类型为 Object;使用一个数组作为参数时,返回集合中所有元素构成的数组,数组类型为作为参数的数组对应的类型;JDK11 开始,参数为函数时,根据这个函数返回集合中所有元素构成的数组。

equals() 方法用于比较两个集合的相等性,具体根据内容还是引用由实现决定。

iterator()spliterator() 方法返回与集合关联的迭代器,stream()parallelStream() 方法返回集合作为数据源的流。

List 接口扩展了 Collection 接口,以有序的方式存储元素,按照索引插入或访问元素。它的形式为

interface List<E>

add(int, E)add(int, Collection) 方法在指定位置插入元素,add(E)add(Collection) 方法在 List 末尾插入元素。replaceAll() 方法修改集合中每个元素。

get(int) 方法返回指定位置的元素,set(int, E) 方法在指定位置设置新元素,indexOf()lastIndexOf() 方法返回指定元素在 List 中的索引。

subList(int, int) 方法返回当前列表指定索引范围的子列表,sort() 方法用于给 List 中元素排序。

JDK9 开始,List 引入了工厂方法 of(),根据传入的参数创建不可修改的小型 List。它有若干个重载方法,形式为

static <E> List<E> of()

无参方法返回空 List,还有 1 到 10 个参数的重载方法,最后还有一个变参的重载方法。

List 不允许 null 元素。

Set 接口扩展了 Collection 接口,它不允许集合中存在重复元素。使用 add() 方法添加元素到集合中时,如果该元素已存在,则返回 false。形式为

interface Set<E>

JDK9,Set 引入了工厂方法 of(),根据传入的参数创建不可修改的小型 Set。它有若干个重载方法,形式为

static <E> Set<E> of()

无参方法返回空 Set,还有 1 到 10 个参数的重载方法,最后还有一个变参的重载方法。

Set 不允许 null 元素。

JDK10,Set 引入了静态方法 copyOf() 用于从参数创建一个 Set,形式为

static <E> Set<E> copyOf(Collection<? extends E> from)

这个方法创建的 Set 不允许修改。

SortedSet 接口扩展了 Set 接口,将集合中的元素以升序排列。形式为

interface SortedSet<E>

first() 方法返回集合中第一个元素,last() 方法返回集合中最后一个元素。subSet(E, E) 方法返回包含第一个参数直到不包含第二个参数为止范围内所有元素构成的 SortedSet,headSet(E) 方法返回小于参数的所有元素构成的 SortedSet,tailSet(E) 方法返回大于等于参数的所有元素构成的 SortedSet。

SortedSet 不允许 null 元素。

NavigableSet 接口扩展了 SortedSet 接口,它支持最接近匹配检索元素。形式为

interface NavigableSet<E>

NavigableSet 不允许 null 元素。

Queue 接口扩展了 Collection 接口,集合中的元素以先进先出的方式访问。形式为

interface Queue<E>

poll()remove() 方法从队头移除元素,不同在于当 Queue 为空时,poll 返回 null,而 remove 抛出异常。peek()element() 方法返回队头元素,不同在于当 Queue 为空时,peek 返回 null,而 element 抛出异常。offer() 方法从队尾添加元素。

Queue 不允许 null 元素。

Deque 接口扩展了 Queue 接口,允许从队头和队尾添加或移除元素。形式为

interface Deque<E>

Deque 不允许 null 元素。

push()pop() 方法可以将 Deque 当栈使用。descendingIterator() 方法返回的迭代器以逆序访问集合中的元素。Deque 的实现导致了它的容量是有限的。当向容量已经满了的 Deque 中添加元素时,addFirst()addLast() 方法抛出异常,offerFirst()offerLast() 方法返回 false。

集合类

一般情况下,集合类是非同步的。

类名 描述
AbstractCollection 实现了大部分的 Collection 接口
AbstractList 扩展了 AbstractCollection,实现了大部分的 List 接口
AbstractSequentialList 扩展了 AbstractList,只能顺序访问元素
LinkedList 扩展了 AbstractSequentialList,实现了链表
ArrayList 扩展了 AbstractList,实现了动态数组
AbstractQueue 扩展了 AbstractCollection,实现了部分 Queue 接口
PriorityQueue 扩展了 AbstractQueue,基于优先级的队列
ArrayDeque 扩展了 AbstractCollection,实现了 Deque 接口,提供动态 Deque 功能
AbstractSet 扩展了 AbstractCollection,实现了大部分的 Set 接口
EnumSet 扩展了 AbstractSet,与枚举元素一起使用
TreeSet 扩展了 AbstractSet,以树的方式存储元素
HashSet 扩展了 AbstractSet,与哈希表一起使用
LinkedHashSet 扩展了 HashSet,允许以插入顺序遍历

ArrayList 扩展了 AbstractList 类,实现了 List 接口。形式为

class ArrayList<E>

ArrayList 支持动态数组功能,大小可增加可缩小。本质上,它是可变长的对象引用数组。构造器如下

// 创建空 ArrayList
ArrayList();
// 使用参数作为初始值创建
ArrayList(Collection<? extends E> c);
// 指定容量大小创建
ArrayList(int capacity);

ensureCapacity() 方法可以在 ArrayList 创建之后设置容量。形式为

// cap 表示设置的最小容量
void ensureCapacity(int cap);

void trimToSize() 将 ArrayList 容量缩减到与当前元素个数相同。

ArrayList 使用 Collection 定义的三个方法可以将集合中的所有元素存放到一个数组中。如下所示

Object[] toArray();
<T> T[] toArray(T[] array);
default <T> T[] toArray(IntFunction<T[]> arrayGen);

LinkedList 扩展了 AbstractSequentialList 类,实现了 List、Deque 和 Queue 接口。形式为

class LinkedList<E>

有如下两个构造器

// 创建空链表
LinkedList();
// 使用 c 的元素作为初始值创建链表
LinkedList(Collection<? extends E> c);

在 LinkedList 首部添加元素使用 addFirst()offerFirst() 方法,尾部添加元素使用 addLast()offerLast() 方法,获取第一个元素使用 getFirst()peekFirst() 方法,获得最后一个元素使用 getLast()peekLast() 方法,移除第一个元素使用 removeFirst()pollFirst() 方法,移除最后一个元素使用 removeLast()pollLast() 方法。上述方法在 Deque 接口中声明。

add(E)add(int, E) 方法在 List 接口中声明。

get(index)set(index, value) 方法用于获取指定索引的值、设置指定索引的值。

HashSet 扩展了 AbstractSet,实现了 Set 接口。它使用哈希表存储元素。形式为

class HashSet<E>

使用哈希表的优点在于 add()contains()remove()size() 方法的执行只需要常量时间。

构造器如下

// 创建空 HashSet
HashSet();
// 使用指定元素初始化 HashSet
HashSet(Collection<? extends E> c);
// 使用指定容量大小创建 HashSet,默认容量 16
HashSet(int capacity);
// 指定容量和填充因子创建 HashSet,当已用空间超过容量与填充因子之积
// 时自动扩容,默认填充因子为 0.75,范围为 [0, 1]
HashSet(int capacity, float fillRatio);

HashSet 不保证元素存储的顺序。

LinkedHashSet 扩展了 HashSet 类。形式为

class LinkedHashSet<E>

它的构造器与 HashSet 相同。LinkedHashSet 内部维护了一个链表,如果遍历元素,遍历顺序与元素被插入集合时的先后次序一致,使用 toString() 方法返回的字符串中元素顺序也与插入的先后次序相同。

TreeSet 类扩展了 AbstractSet 类,实现了 NavigableSet 接口。它的内部使用树以升序的方式存储元素。查询操作的性能高。形式为

class TreeSet<T>

构造器如下

TreeSet();
TreeSet(Collection<? extends E> c);
// 根据传入的比较器来排序元素
TreeSet(Comparator<? super E> comp);
TreeSet(SortedSet<E> ss);

PriorityQueue 扩展了 AbstractQueue 类,实现了 Queue 接口。它存储的元素优先级基于比较器。容量大小随添加的元素自动增加。形式为

class PriorityQueue<E>;

它的构造器如下

PriorityQueue();
PriorityQueue(int capacity);
// 集合中元素的优先级根据传入的比较器决定
PriorityQueue(Comparator<? super E> comp);
PriorityQueue(int capacity, Comparator<? super E> comp);
PriorityQueue(Collection<? extends E> c);
PriorityQueue(PriorityQueue<? extends E> c);
PriorityQueue(SortedSet<? extends E> c);

空优先队列的初始容量是 11。没有传入比较器时,元素的优先级根据元素类型的默认比较器确定。它以升序存储元素。

它的 comparator() 方法返回使用的比较器。如果元素以自然序存储,则返回 null。形式为

Comparator<? super E> comparator();

使用迭代器遍历优先队列时,访问元素的顺序是未知的。

ArrayDeque 扩展了 AbstractCollection 类,实现了 Deque 接口。它的容量是动态变化的。形式为

class ArrayDeque<E>

构造器如下

ArrayDeque();
ArrayDeque(int size);
ArrayDeque(Collection <? extends E> c);

空 ArrayDeque 的初始容量是 16。

EnumSet 扩展了 AbstractSet 类,实现了 Set 接口。它能存储的元素只能是枚举类型。没有构造器,使用工厂方法创建对象。形式为

class EnumSet<E extends Enum<E>>

通过迭代器访问集合

Iterator 接口用于遍历集合中的元素,访问或移除元素。ListIterator 接口扩展了 Iterator 接口,用于双向遍历列表或修改元素。形式如下

interface Iterator<E>
interface ListIterator<E>

从 JDK8 开始,Spliterator 接口也可以用于遍历集合中的元素。

使用迭代器遍历集合中的元素的步骤如下

  1. 集合类调用 iterator() 方法返回迭代器。
  2. 迭代器调用 hasNext() 方法开始循环,当该方法返回 true 时,调用 next() 方法获取集合中的元素,直到 hasNext() 方法返回 false。

实现了 List 接口的集合可以调用 listIterator() 方法返回迭代器,这个迭代器可以向前和向后遍历集合,也可以修改元素。

实现了 Iterable 接口的集合可以使用 for-each 语句循环前向遍历集合中的元素,所有的集合类都实现了这个接口。

Spliterators

JDK8 引入了另一个迭代器 spliterator,由 Spliterator 接口提供。spliterator 提供了并发迭代的功能,支持并发编程。它提供了更方便的方式使用 hasNext 和 next 操作。形式为

interface Spliterator<T>

遍历元素使用 spliterator 的 tryAdvance() 方法,当集合中有元素时,执行操作,返回 true;否则返回 false。对集合中每个元素执行相同的操作可以使用 forEachRemaining() 方法。这两个方法的参数类型为函数式接口 Consumer,接口有一个抽象方法 void accept(T)

List<Integer> arr = new ArrayList<>();
arr.add(1);
arr.add(2);
arr.add(3);

var spite = arr.spliterator();
// 1 2 3
while(spite.tryAdvance(e -> System.out.print(e + " ")));

Spliterator 接口有内嵌的子接口 Spliterator.OfDouble、Spliterator.OfInt 和 Spliterator.OfLong 用于对应的原始类型。Spliterator.OfPrimitive() 方法返回上述 3 个子接口的父接口。

RandomAccess 接口

RandomAccess 接口没有定义方法,实现该接口的集合表示可以有效地随机访问集合中的元素。

使用 Maps

map 中键必须唯一。有些 map 允许键或值是 null,有些不允许。

map 没有实现 Iterable 接口,因此 map 不能使用 for-each 语句遍历元素,也没有与之关联的迭代器。但可以获取 map 的集合视图。

接口名称 描述
Map 键唯一
Map.Entry Map 的内部类,用于表示 map 的元素,即键值对
SortedMap 扩展了 Map,键以升序存储
NavigableMap 扩展了 SortedMap,基于最接近匹配搜索元素

Map 接口中需要键唯一。形式为

interface Map<K, V>

get() 方法将传入的参数作为键返回对应的值。put() 方法向 Map 中插入新元素,作为参数的元素是一个键值对。

Map 不属于集合,因为没有实现 Collection 接口。entrySet() 方法将 Map 中的键值对作为元素构成 Set 返回。keySet() 方法将 Map 的键作为元素构成 Set 返回。values() 方法将 Map 中的值作为元素构成集合返回。

JDK9,给 Map 引入了工厂方法 of(),用于创建不可修改的小型 Map。形式为

// 创建空 Map
static <K, V> Map<K, V> of()

其他重载的 of() 方法接收 1 到 10 个参数,使用参数作为元素创建 Map。null 不允许作为键或值。

SortedMap 接口扩展了 Map 接口,保证 Map 中的元素以键升序排列。形式为

interface SortedMap<K, V>

headMap(K end) 方法返回 Map 中第一个元素开始,键小于 end 的最后一个元素为止的所有元素构成的 Map。tailMap(K start) 方法返回 Map 中第一个键大于等于 start 的元素开始,到最后一个元素为止的所有元素构成的 Map。subMap(K start, K end) 方法返回 Map 中第一个键大于等于 start 的元素开始,键小于 end 的最后一个元素为止的所有元素构成的 Map。firstKey() 方法返回第一个键。lastKey() 方法返回最后一个键。

NavigableMap 接口扩展了 SortedMap,提供了使用一个或多个键基于最接近匹配搜索元素的功能。形式为

interface NavigableMap<K, V>

不允许使用 null 作为键或值。

Map.Entry 接口提供了使用 Map 中元素的功能。Map 的 entrySet() 方法返回的 Set 中元素的类型为 Map.Entry。形式为

interface Map.Entry<K, V>

静态方法 comparingByKey() 返回使用键比较元素的比较器。静态方法 comparingByValue() 返回使用值比较元素的比较器。

实现了 Map 接口的类如下所示

类名 描述
AbstractMap 实现了大部分的 Map 接口
EnumMap 扩展了 AbstractMap,使用 enum 作为键
HashMap 扩展了 AbstractMap,使用哈希表
LinkedHashMap 扩展了 HashMap,允许以插入顺序遍历
TreeMap 扩展了 AbstractMap,使用树
WeakHashMap 扩展了 AbstractMap,使用弱键和哈希表
IdentityHashMap 扩展了 AbstractMap,使用引用比较相等性

WeakHashMap 中,当键不再被除了该容器的变量引用之后,容器中键对应的元素会被垃圾回收。

HashMap 扩展了 AbstractMap 类,实现了 Map 接口。它使用哈希表存储元素,get()put() 方法可以在常数时间内完成。形式为

class HashMap<K, V>

构造器如下

HashMap();
HashMap(Map<? extends K, ? extends V> m);
HashMap(int capacity);
HashMap(int capacity, float fillRatio);

默认容量 16,默认填充因子 0.75。

HashMap 不保证存储元素的顺序。

TreeMap 扩展了 AbstractMap 类,实现了 Map 接口。它以树结构存储元素,以键升序存储,查询效率高。形式为

class TreeMap<K, V>

构造器如下

TreeMap();
// 使用 comp 比较键的大小从而升序存储元素
TreeMap(Comparator<? super K> comp);
TreeMap(Map<? extends K, ? extends V> m);
TreeMap(SortedMap<K, ? extends V> sm);

LinkedHashMap 扩展了 HashMap 类,内部使用链表记录元素插入的顺序,所以能够以元素插入的顺序遍历元素。也可以创建以元素最后被访问的顺序返回的 Map。形式为

class LinkedHashMap<K, V>

构造器如下

LinkedHashMap();
LinkedHashMap(Map<? extends K, ? extends V> m);
LinkedHashMap(int capacity);
// 默认容量 16,填充因子 0.75
LinkedHashMap(int capacity, float fillRatio);
// order 为 false 使用元素插入顺序
// 为 true 使用元素最后访问顺序
LinkedHashMap(int capacity, float fillRatio, boolean order);

protected boolean removeEldestEntry(Map.Entry<K,V> e) 方法通过 put() 方法和 putAll() 方法调用,e 表示最旧的元素。默认情况下,不执行任何操作,直接返回 false。如果重写该方法,当移除了 Map 中最旧的元素,应该返回 true;否则返回 false。

IdentityHashMap 扩展了 AbstractMap 类,实现了 Map 接口。类似于 HashMap,除了使用引用比较元素相等性。形式为

class IdentityHashMap<K, V>

EnumMap 扩展了 AbstractMap 类,实现了 Map 接口。保证元素的键必须是 enum 类型。形式为

class EnumMap<K extends Enum<K>, V>

构造器如下

EnumMap(Class<K> kType);
EnumMap(Map<K, ? extends V> m);
EnumMap(EnumMap<K, ? extends V> em);

比较器

比较器用于控制有序集合中元素排序的方式。形式为

interface Comparator<T>

JDK8 之前,Comparator 接口定义了两个方法,int compare(T o1, T o2) 方法用于比较两个对象大小返回负值、0 或正值,该方法用于控制元素排序方式。boolean equals(Object o) 方法比较相等性,如果调用对象和参数对象都是 Comparator 对象同时采用了相同的顺序,则返回 true;否则返回 false。

JDK8 引入了如下方法。
default Comparator<T> reversed() 方法返回当前比较器的逆序比较器。
static <T extends Comparable<? super T>> Comparator<T> reverseOrder() 方法返回元素自然序的逆序比较器。
static <T extends Comparable<? super T>> Comparator<T> naturalOrder() 方法返回元素自然序的比较器。
static <T> Comparator<T> nullsFirst(Comparator<? super T> comp) 方法将 null 元素看作比非 null 元素小,非 null 元素的比较使用 comp。如果 comp 为 null,所有非 null 元素被视为相等。
static <T> Comparator<T> nullsLast(Comparator<? super T> comp) 方法将 null 元素看作比非 null 元素大,非 null 元素的比较使用 comp。如果 comp 为 null,所有非 null 元素被视为相等。

default Comparator<T> thenComparing(Comparator<? super T> then) 方法返回一个比较器,这个比较器可以执行两次比较。当第一次比较结果相等时,使用 then 比较器进行第二次比较。

default <U extends Comparable<? super U>>
  Comparator<T> thenComparing(Function<? super T, ? extends U> getKey)

方法当第一次比较结果相等时,使用 getKey 表示的函数获得下一个比较的键。U 表示键的类型。

default <U> Comparator<T>
  thenComparing(Function<? super T, ? extends U> getKey, Comparator<? super U> keyCmp)

方法当第一次比较结果相等时,使用 getKey 表示的函数获得下一个比较的键,使用比较器 keyCmp 比较键。U 表示键的类型。

下面 3 个类似的方法用于原始类型比较。
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> getKey)
default Comparator<T> thenComparingInt(ToIntFunction<? super T> getKey)
default Comparator<T> thenComparingLong(ToLongFunction<? super T> getKey)

static <T, U extends Comparable<? super U>> Comparator<T>
  comparing(Function<? super T, ? extends U> getKey)

方法返回一个比较的键由 getKey 表示的函数获得的比较器。

static <T, U> Comparator<T>
  comparing(Function<? super T, ? extends U> getKey, Comparator<? super U> keyCmp)

方法返回使用 getKey 表示的函数获得比较的键,使用比较器 keyCmp 比较键的比较器。

下面 3 个类似的方法用于原始类型比较。
static <T> Comparator<T> ComparingDouble(ToDoubleFunction<? super T> getKey)
static <T> Comparator<T> ComparingInt(ToIntFunction<? super T> getKey)
static <T> Comparator<T> ComparingLong(ToLongFunction<? super T> getKey)

// 比较 LastName
class CmpLast implements Comparator<String> {
  public int compare(String a, String b) {
    return a.substring(a.lastIndexOf(" ")).compareToIgnoreCase(b.substring(b.lastIndexOf(" ")))
  }
}

// 比较 FullName
class CmpFirst implements Comparator<String> {
  public int compare(String a, String b) {
    return a.compareToIgnoreCase(b);
  }
}

class Demo {
  public static void main(String[] args) {
    var cmp = new CmpLast().thenComparing(new CmpFirst());
    // 使用自定义的比较器为元素排序
    // 先比较 LastName,若相等再比较全名
    var tm = new TreeMap<String, Double>(cmp);
  }
}

集合算法

Collections 类中定义了很多静态方法用于集合和 map。

以 checked 开头的方法返回一个运行时类型安全的集合视图,如果向集合中插入类型不兼容的元素,会抛出 ClassCastException。

以 synchronized 开头的方法返回集合的同步(线程安全)副本,一般集合都是线程不安全的。使用同步集合时,遍历元素需要在 synchronized 块中进行。

以 unmodifiable 开头的方法返回集合的不可修改版本。

Arrays

Arrays 中定义的方法作为沟通集合和数组之间的桥梁。

static <T> List asList(T... arr) 方法使用指定数组中的元素构建 List 返回。

binarySearch() 方法在有序数组查找指定值,找到则返回该值的索引,没找到则返回一个负值。

// xx 表示 byte/short/int/long/char/float/double/Object
// xx 在本节使用方式下同
static int binarySearch(xx[] arr, xx value);
static <T> int binarySearch(T[] arr, T value, Comparator<? super T> c);

copyOf() 方法返回指定数组指定长度的元素构成的新数组。当指定长度比数组长度长时,后面缺失的内容根据元素类型填充 0、null 或 false。

static xx[] copyOf(xx[] arr, int len);
static <T> T[] copyOf(T[] arr, int len);
// 返回的数组类型由 resultT 指定
static <T,U> T[] copyOf(U[] source, int len, Class<? extends T[]> resultT);

copyOfRange() 方法返回指定数组指定范围的元素构成的新数组。当指定范围比数组长度长时,后面缺失的内容根据元素类型填充 0、null 或 false。

static xx[] copyOfRange(xx[] source, int start, int end);
static <T> T[] copyOfRange(T[] source, int start, int end);
static <T, U> T[] copyOfRange(U[] source, int start, int end, Class<? extends T[]> resultT);

equals() 方法比较两个数组是否相等。

static boolean equals(xx[] arr1, xx[] arr2);

static boolean deepEquals(Object[] a, Object[] b) 方法用于比较两个数组是否相等,数组里可以有嵌套数组,即多维数组。

fill() 方法使用指定值填充数组。有指定范围的重载版本。

static void fill(xx[] arr, xx value);

sort() 方法以升序排列数组中的元素。有指定范围的重载版本。

static void sort(xx[] arr);
static <T> void sort(T[] arr, Comparator<? super T> c);

parallelSort() 方法以并发的方式升序排列数组元素。有指定范围的重载版本。

static void parallelSort(xx[] arr);
static <T extends Comparable<? super T>> void parallelSort(T[] arr);
static <T> void parallelSort(T[] arr, Comparator<? super T> c);

spliterator() 方法返回 spliterator 迭代器遍历数组。有指定范围的重载版本。

static Spliterator.OfDouble spliterator(double[] arr);
static Spliterator.OfInt spliterator(int[] arr);
static Spliterator.OfLong spliterator(long[] arr);
static <T> Spliterator spliterator(T[] arr);

stream() 方法返回流,支持 Stream 接口。有指定范围的重载版本。

static DoubleStream stream(double[] arr);
static IntStream stream(int[] arr);
static LongStream stream(long[] arr);
static <T> Stream stream(T[] arr);

setAll()parallelSetAll() 方法给所有元素赋值。

static void parallelPrefix(xx[] arr, XxBinaryOperator func) 方法接收一个函数,使用这个函数对当前元素和前一个元素进行二元操作。

int[] arr = {1, 2, 3};
Arrays.parallelPrefix(arr, (a, b) -> a + b);
// 1 3 6
Arrays.stream(arr).forEach(e -> System.out.print(e + " "));

JDK9 为 Arrays 引入了 3 个新方法。compare() 方法比较两个数组,compareUnsigned() 方法以无符号的方式比较两个整型数组,mismatch() 方法返回两个数组第一个不相等元素的索引,如果数组相同,返回 -1。

遗留类和接口

所有的遗留类和接口都是同步的,前述提到的所有集合类和接口都是非同步的。
遗留类有如下 5 种

  • Dictionary
  • Hashtable
  • Properties
  • Stack
  • Vector

Enumeration 接口用于枚举集合中的元素。形式为

interface Enumeration<E>

有两个抽象方法 boolean hasMoreElements()E nextElement()。JDK9 引入了默认方法 default Iterator<E> asIterator() 返回 Enumeration 的迭代器。如果已经遍历了部分元素,则该迭代器指向未遍历的第一个元素。

Vector 实现了动态数组,扩展了 AbstractList,实现了 List 和 Iterable 接口。形式为

class Vector<E>

构造器如下

Vector();
Vector(int size);
// inc 指定了当 Vector 扩容时,增加的容量大小
// 不指定时,以 2 倍的方式扩充容量
Vecotr(int size, int inc);
Vector(Collection<? extends E> c);

vector 定义了 3 个 protected 成员变量,int capacityIncrement 表示扩容时增加的容量大小,int elementCount 存储当前元素个数,Object[] elementData 存储 vector 中的元素。

addElement() 方法添加元素,elementAt() 方法获取指定索引元素,firstElement() 方法获取第一个元素,lastElement() 方法获取最后一个元素,indexOf()lastIndexOf() 方法返回指定元素的索引,removeElement()removeElementAt() 方法移除元素。

Stack 形式为

class Stack<E>

empty() 方法判断 stack 是否为空,peek() 方法返回栈顶元素,pop() 方法移除并返回栈顶元素,push() 方法添加元素,search() 方法搜索指定元素是否在栈内,如果在,返回获得该元素需要 pop 的次数。

Dictionary 是存储键值对的抽象类。形式为

class Dictionary<K, V>

定义的抽象方法有:put() 方法添加元素,get() 方法通过键获取值,keys() 方法返回由键组成的 Enumeration,elements() 方法返回由值组成的 Enumeration。size() 方法返回元素个数,isEmpty() 方法判断是否为空,remove() 方法移除元素。

Hashtable 是 Dictionary 类的具体子类,实现了 Map 接口。以键的哈希值作为键对应值的索引。形式为

class Hashtable<K, V>

哈希表能够存储的键,必须实现了自己的 hashCode()equals() 方法。构造器如下

// 默认容量 11,默认填充因子 0.75
Hashtable();
Hashtable(int size);
Hashtable(int size, float fillRatio);
Hashtable(Map<? extends K, ? extends V> m);

Properties 是 Hashtable 的子类。键和值的类型为 String,自身不是泛型,部分方法是泛型。是 System.getProperties() 方法的返回值类型。它定义了 protected volatile 实例变量 Properties defaults 存储和 Properties 对象关联的默认属性列表。

构造器如下

// 无默认值
Properties();
// 默认值为 prpDefault
Properties(Properties prpDefault);
Properties(int capacity);

Properties 能够给某个键指定默认值或者给整个对象指定默认 Properties 对象。当没有对应的键时,返回指定的默认值或者从默认 Properties 对象中查找。如 getProperty("k", "default v") 找不到对应的键 “k” 时,返回默认值 “default v”。

store()load() 方法用于存储 Properties 对象到文件和加载文件到 Properties 对象。

static void m() {
  var p = new Properties();
  var fin = new FileInputStream("fileName.suffix");
  if (fin != null) {
    p.load(fin);
    fin.close();
  }
  var fout = new FileOutputStream("fileName.suffix");
  p.store(fout, "comments");
}

参考

[1] Herbert Schildt, Java The Complete Reference 11th, 2019.

 posted on 2024-04-23 14:51  x-yun  阅读(4)  评论(0编辑  收藏  举报