2021-11-11

Java 集合

Collection接口

集合层次结构中的根接口。一个集合代表一组对象,称为它的元素。一些集合允许重复元素,而另一些则不允许。有些是有序的,有些是无序的。 JDK 不提供此接口的任何直接实现:它提供了更具体的子接口(如 Set 和 List)的实现。此接口通常用于传递集合并在需要最大通用性的地方操作它们。
Bags 或 multisets(可能包含重复元素的无序集合)应该直接实现这个接口。
所有通用 Collection 实现类(通常通过其子接口之一间接实现 Collection)应该提供两个“标准”构造函数:一个 void(无参数)构造函数,它创建一个空集合,以及一个具有单个参数类型的构造函数集合,它创建一个具有与其参数相同的元素的新集合。实际上,后一个构造函数允许用户复制任何集合,生成所需实现类型的等效集合。没有办法强制执行此约定(因为接口不能包含构造函数),但 Java 平台库中的所有通用 Collection 实现都符合。
此接口中包含的“破坏性”方法,即修改它们操作的集合的方法,如果此集合不支持该操作,则指定为抛出 UnsupportedOperationException。在这种情况下,如果调用对集合没有影响,则这些方法可能(但不是必需)抛出 UnsupportedOperationException。例如,如果要添加的集合为空,则在不可修改的集合上调用 addAll(Collection) 方法可能(但不是必须)抛出异常。
一些集合实现对它们可能包含的元素有限制。例如,有些实现禁止空元素,有些实现对其元素的类型有限制。尝试添加不合格的元素会引发未经检查的异常,通常为 NullPointerException 或 ClassCastException。尝试查询不合格元素的存在可能会引发异常,或者可能只是返回 false;一些实现会表现出前一种行为,而另一些会表现出后者。更一般地,尝试对不合格元素执行操作,其完成不会导致将不合格元素插入到集合中,这可能会引发异常,也可能会成功,具体取决于实现的选择。在此接口的规范中,此类异常被标记为“可选”。
由每个集合来确定自己的同步策略。在没有更强大的实现保证的情况下,未定义的行为可能是由于在另一个线程正在改变的集合上调用任何方法;这包括直接调用、将集合传递给可能执行调用的方法以及使用现有迭代器检查集合。
Collections Framework 接口中的许多方法都是根据 equals 方法定义的。例如, contains(Object o) 方法的规范说:“当且仅当此集合包含至少一个元素 e 使得 (onull ? enull : o.equals(e)) 时才返回 true .”本规范不应被解释为暗示使用非空参数 o 调用 Collection.contains 将导致为任何元素 e 调用 o.equals(e)。实现可以自由地实现优化,从而避免 equals 调用,例如,首先比较两个元素的哈希码。 (Object.hashCode() 规范保证哈希码不相等的两个对象不能相等。)更一般地说,各种集合框架接口的实现可以自由地利用底层对象方法的指定行为,只要实现者认为合适.
一些对集合执行递归遍历的集合操作可能会失败,但对于自引用实例(其中集合直接或间接包含自身)除外。这包括 clone()、equals()、hashCode() 和 toString() 方法。实现可以选择性地处理自引用场景,但是大多数当前的实现都没有这样做。
此接口是 Java 集合框架的成员。
实施要求:
默认方法实现(继承或以其他方式)不应用任何同步协议。如果 Collection 实现具有特定的同步协议,则它必须覆盖默认实现以应用该协议。
也可以看看:
Set、List、Map、SortedSet、SortedMap、HashSet、TreeSet、ArrayList、LinkedList、Vector、Collections、Arrays、AbstractCollection
类型参数: – 此集合中元素的类型

public interfeace Collection<E> extends Interable<E>{

	返回此集合中的元素数。 如果此集合包含多个 Integer.MAX_VALUE 元素,则返回 Integer.MAX_VALUE。
返回:
此集合中的元素数
	int size();


	返回:
如果此集合不包含任何元素,则为 true
	boolean isEmpty();

如果此集合包含指定的元素,则返回 true。 更正式地说,当且仅当此集合包含至少一个元素 e 使得 (o==null ? e==null : o.equals(e)) 时才返回 true。
参数:
o - 要测试其在此集合中是否存在的元素
返回:
如果此集合包含指定的元素,则为 true
抛出:
ClassCastException – 如果指定元素的类型与此集合不兼容(可选)
NullPointerException – 如果指定的元素为 null 并且此集合不允许 null 元素(可选)
	boolean contains(Object o);

返回此集合中元素的迭代器。 没有关于元素返回顺序的保证(除非这个集合是提供保证的某个类的实例)。
返回:
此集合中元素的迭代器
	Iterator<E> iterator();


返回一个包含此集合中所有元素的数组。 如果此集合对其迭代器返回其元素的顺序做出任何保证,则此方法必须以相同的顺序返回元素。
返回的数组将是“安全的”,因为此集合不维护对它的引用。 (换句话说,即使此集合由数组支持,此方法也必须分配一个新数组)。 因此调用者可以自由地修改返回的数组。
此方法充当基于数组和基于集合的 API 之间的桥梁。
返回:
包含此集合中所有元素的数组
	Object[] toArray();


返回一个包含此集合中所有元素的数组;返回数组的运行时类型是指定数组的类型。如果集合适合指定的数组,则在其中返回。否则,将使用指定数组的运行时类型和此集合的大小分配一个新数组。
如果此集合适合指定的数组并有剩余空间(即,该数组的元素比此集合多),则紧跟该集合末尾的数组中的元素将设置为 null。 (仅当调用者知道此集合不包含任何空元素时,这才可用于确定此集合的长度。)
如果此集合对其迭代器返回其元素的顺序做出任何保证,则此方法必须以相同的顺序返回元素。
与 toArray() 方法一样,此方法充当基于数组和基于集合的 API 之间的桥梁。此外,该方法允许精确控制输出数组的运行时类型,并且在某些情况下可用于节省分配成本。
假设 x 是一个已知只包含字符串的集合。以下代码可用于将集合转储到新分配的 String 数组中:
           String[] y = x.toArray(new String[0]);
请注意 toArray(new Object[0]) 在功能上与 toArray() 相同。
参数:
a – 要存储此集合的元素的数组,如果它足够大;否则,将为此分配一个相同运行时类型的新数组。
类型参数:
<T> – 包含集合的数组的运行时类型
返回:
包含此集合中所有元素的数组
抛出:
ArrayStoreException – 如果指定数组的运行时类型不是此集合中每个元素的运行时类型的超类型
NullPointerException – 如果指定的数组为空
	<T> T[] toArray(T[] a);
	
	
	确保此集合包含指定的元素(可选操作)。如果此集合因调用而更改,则返回 true。 (如果此集合不允许重复并且已经包含指定的元素,则返回 false。)
支持此操作的集合可能会对可以添加到此集合中的元素设置限制。特别是,一些集合会拒绝添加空元素,而另一些集合会对可能添加的元素类型施加限制。集合类应该在他们的文档中清楚地指定对可以添加哪些元素的任何限制。
如果集合由于任何原因而拒绝添加特定元素,但它已包含该元素,则它必须抛出异常(而不是返回 false)。这保留了在此调用返回后集合始终包含指定元素的不变性。
参数:
e - 要确保其在此集合中存在的元素
返回:
如果此集合因调用而更改,则为 true
抛出:
UnsupportedOperationException – 如果此集合不支持添加操作
ClassCastException – 如果指定元素的类阻止将其添加到此集合中
NullPointerException – 如果指定的元素为 null 并且此集合不允许 null 元素
IllegalArgumentException – 如果元素的某些属性阻止将其添加到此集合中
IllegalStateException – 如果由于插入限制此时无法添加元素
	boolean add(E e);



从此集合中移除指定元素的单个实例(如果存在)(可选操作)。 更正式地说,如果该集合包含一个或多个这样的元素,则删除满足 (o==null ? e==null : o.equals(e)) 的元素 e。 如果此集合包含指定的元素(或等效地,如果此集合因调用而更改),则返回 true。
参数:
o - 要从此集合中删除的元素(如果存在)
返回:
如果由于此调用而删除了元素,则为 true
抛出:
ClassCastException – 如果指定元素的类型与此集合不兼容(可选)
NullPointerException – 如果指定的元素为 null 并且此集合不允许 null 元素(可选)
UnsupportedOperationException – 如果此集合不支持删除操作
	boolean remove(Object o);


如果此集合包含指定集合中的所有元素,则返回 true。
参数:
c – 要检查此集合中是否包含的集合
返回:
如果此集合包含指定集合中的所有元素,则为 true
抛出:
ClassCastException – 如果指定集合中一个或多个元素的类型与此集合不兼容(可选)
NullPointerException – 如果指定的集合包含一个或多个空元素并且该集合不允许空元素(可选),或者如果指定的集合为空。
也可以看看:
包含(对象)
	boolean containsAll(Collection<?> c);
	

将指定集合中的所有元素添加到此集合(可选操作)。如果在操作进行时修改了指定的集合,则此操作的行为未定义。 (这意味着如果指定的集合是这个集合,并且这个集合是非空的,那么这个调用的行为是未定义的。)
参数:
c – 包含要添加到此集合的元素的集合
返回:
如果此集合因调用而更改,则为 true
抛出:
UnsupportedOperationException – 如果此集合不支持 addAll 操作
ClassCastException – 如果指定集合的​​元素的类阻止将其添加到此集合
NullPointerException – 如果指定的集合包含空元素并且此集合不允许空元素,或者指定的集合为空
IllegalArgumentException – 如果指定集合的​​某个元素的某些属性阻止将其添加到此集合中
IllegalStateException - 如果由于插入限制,此时不能添加所有元素
也可以看看:
添加(对象)
	boolean addAll(Collection<? extends E> c);
	

删除也包含在指定集合中的所有此集合的元素(可选操作)。 此调用返回后,此集合将不包含与指定集合相同的元素。
参数:
c – 包含要从此集合中删除的元素的集合
返回:
如果此集合因调用而更改,则为 true
抛出:
UnsupportedOperationException – 如果此集合不支持 removeAll 方法
ClassCastException – 如果此集合中一个或多个元素的类型与指定的集合不兼容(可选)
NullPointerException – 如果此集合包含一个或多个 null 元素并且指定的集合不支持 null 元素(可选),或者指定的集合为 null
也可以看看:
删除(对象),包含(对象)
	boolean removeAll(Collection<?> c);
	
删除此集合中满足给定谓词的所有元素。 在迭代期间或由谓词引发的错误或运行时异常被中继到调用者。
参数:
filter – 一个谓词,它为要删除的元素返回 true
返回:
如果删除了任何元素,则为 true
抛出:
NullPointerException – 如果指定的过滤器为空
UnsupportedOperationException – 如果无法从此集合中删除元素。 如果无法删除匹配元素,或者通常不支持删除,则实现可能会抛出此异常。
实施要求:
默认实现使用其迭代器遍历集合的所有元素。 使用 Iterator.remove() 删除每个匹配的元素。 如果集合的迭代器不支持删除,则将在第一个匹配元素上抛出 UnsupportedOperationException。
自从:
1.8

	defult boolean removeIf(Predicate<? super E> filter){}
	

仅保留此集合中包含在指定集合中的元素(可选操作)。 换句话说,从该集合中删除所有未包含在指定集合中的元素。
参数:
c – 包含要保留在此集合中的元素的集合
返回:
如果此集合因调用而更改,则为 true
抛出:
UnsupportedOperationException – 如果此集合不支持 retainAll 操作
ClassCastException – 如果此集合中一个或多个元素的类型与指定的集合不兼容(可选)
NullPointerException – 如果此集合包含一个或多个空元素并且指定的集合不允许空元素(可选),或者指定的集合为空
也可以看看:
删除(对象),包含(对象)
	boolean retainAll(Collection<?> c);
	


从此集合中删除所有元素(可选操作)。 此方法返回后,集合将为空。
抛出:
UnsupportedOperationException – 如果此集合不支持清除操作
	void clear();


比较指定对象与此集合是否相等。
虽然 Collection 接口没有对 Object.equals 的一般契约添加任何规定,但“直接”实现 Collection 接口的程序员(换句话说,创建一个是 Collection 但不是 SetList 的类)必须小心如果他们选择覆盖 Object.equals。没有必要这样做,最简单的做法是依赖 Object 的实现,但实现者可能希望实现一个“值比较”来代替默认的“引用比较”。 ( ListSet 接口要求进行这样的值比较。)
Object.equals 方法的一般约定规定,equals 必须是对称的(换句话说,a.equals(b) 当且仅当 b.equals(a))。 List.equals 和 Set.equals 的契约声明列表仅等于其他列表,并设置为其他集合。因此,当将此集合与任何列表或集合进行比较时,既不实现 List 也不实现 Set 接口的集合类的自定义 equals 方法必须返回 false。 (根据相同的逻辑,不可能编写一个正确实现 SetList 接口的类。)
参数:
o - 要与此集合进行相等性比较的对象
返回:
如果指定的对象等于此集合,则为 true
也可以看看:
Object.equals(Object), Set.equals(Object), List.equals(Object)
	booolean equals(Object o);


	返回此集合的哈希码值。 虽然 Collection 接口没有对 Object.hashCode 方法的通用约定添加任何规定,但程序员应该注意,任何重写 Object.equals 方法的类也必须重写 Object.hashCode 方法以满足 Object 的通用约定 .hashCode 方法。 特别是,c1.equals(c2) 意味着 c1.hashCode()==c2.hashCode()。
返回:
此集合的哈希码值
也可以看看:
Object.hashCode(), Object.equals(Object)
	int hashcode();

在此集合中的元素上创建一个 Spliterator。 实现应该记录拆分器报告的特征值。 如果拆分器报告 Spliterator.SIZED 并且此集合不包含元素,则不需要报告此类特征值。
	默认实现应该被可以返回更有效的拆分器的子类覆盖。为了保留 stream()parallelStream()} 方法的预期惰性行为,拆分器应该具有 IMMUTABLE 或 CONCURRENT 的特性,或者是后期绑定。如果这些都不实用,则覆盖类应描述拆分器的绑定和结构干扰的文档化策略,并应覆盖 stream()parallelStream() 方法以使用拆分器的供应商创建流,如下所示: 
     Stream<E> s = StreamSupport.stream(() -> spliterator(), spliteratorCharacteristics)
这些要求确保由 stream()parallelStream() 方法生成的流将反映在启动终端流操作时集合的内容。
返回:
此集合中元素的 Spliterator
实施要求:
默认实现从集合的迭代器创建一个后期绑定拆分器。拆分器继承了集合迭代器的快速失败属性。
创建的 Spliterator 报告 Spliterator.SIZED。
实施注意事项:
创建的 Spliterator 还会报告 Spliterator.SUBSIZED。
如果拆分器不包含任何元素,则报告除 SIZED 和 SUBSIZED 之外的其他特征值不会帮助客户端控制、专门化或简化计算。但是,这确实允许共享使用不可变的空拆分器实例(请参阅 Spliterators.emptySpliterator())用于空集合,并使客户端能够确定此类拆分器是否不包含任何元素。
	default Spliterator<E> spliterator(){}


返回一个以此集合作为源的顺序流。
当 spliterator() 方法无法返回 IMMUTABLE、CONCURRENT 或后期绑定的 spliterator 时,应覆盖此方法。 (有关详细信息,请参阅 spliterator()。)
返回:
此集合中元素的顺序流
实施要求:
默认实现从集合的 Spliterator 创建一个顺序流。
自从:
1.8	
	default Stream<E> stream(){}
	
返回一个可能的并行 Stream,以此集合作为其源。 允许此方法返回顺序流。
当 spliterator() 方法无法返回 IMMUTABLE、CONCURRENT 或后期绑定的 spliterator 时,应覆盖此方法。 (有关详细信息,请参阅 spliterator()。)
返回:
在此集合中的元素上的可能并行 Stream
实施要求:
默认实现从集合的 Spliterator 创建一个并行流。
自从:
1.8
	default Stream<E> parallelStream(){}
}

Map

将键映射到值的对象。地图不能包含重复的键;每个键最多可以映射到一个值。
这个接口取代了 Dictionary 类,它是一个完全抽象的类而不是一个接口。
Map 接口提供了三个集合视图,允许将地图的内容视为一组键、一组值或一组键值映射。地图的顺序定义为地图集合视图上的迭代器返回其元素的顺序。一些地图实现,如 TreeMap 类,对它们的顺序做出特定保证;其他的,比如 HashMap 类,则没有。
注意:如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是映射中的键,则不会指定映射的行为。此禁令的一个特殊情况是不允许映射将自身包含为键。虽然允许映射将自身包含为值,但建议格外小心:在此类映射上不再明确定义 equals 和 hashCode 方法。
所有通用映射实现类都应该提供两个“标准”构造函数:一个创建空映射的 void(无参数)构造函数,以及一个带有 Map 类型的单个参数的构造函数,它创建一个具有相同键值的新映射映射作为其参数。实际上,后一个构造函数允许用户复制任何映射,生成所需类的等效映射。没有办法强制执行此建议(因为接口不能包含构造函数),但 JDK 中的所有通用映射实现都符合。
此接口中包含的“破坏性”方法,即修改它们操作的映射的方法,如果此映射不支持该操作,则指定为抛出 UnsupportedOperationException。在这种情况下,如果调用对地图没有影响,则这些方法可能(但不是必需)抛出 UnsupportedOperationException。例如,如果要“叠加”映射的映射为空,则在不可修改的映射上调用 putAll(Map) 方法可能(但不是必需)引发异常。

一些地图实现对它们可能包含的键和值有限制。例如,有些实现禁止空键和值,有些实现对其键的类型有限制。尝试插入不合格的键或值会引发未经检查的异常,通常为 NullPointerException 或 ClassCastException。尝试查询不合格的键或值的存在可能会引发异常,或者可能只是返回 false;一些实现会表现出前一种行为,而另一些会表现出后者。更一般地,尝试对不合格的键或值执行操作,其完成不会导致将不合格的元素插入到映射中,这可能会引发异常,或者可能会成功,具体取决于实现的选择。在此接口的规范中,此类异常被标记为“可选”。
Collections Framework 接口中的许多方法都是根据 equals 方法定义的。例如, containsKey(Object key) 方法的规范说:“当且仅当此映射包含键 k 的映射使得 (key = = null ? k ==null : key.equals(k) )”本规范不应被解释为暗示使用非空参数键调用 Map.containsKey 将导致为任何键 k 调用 key.equals(k)。实现可以自由地实现优化,从而避免 equals 调用,例如,通过首先比较两个键的哈希码。 (Object.hashCode() 规范保证哈希码不相等的两个对象不能相等。)更一般地说,各种集合框架接口的实现可以自由地利用底层对象方法的指定行为,只要实现者认为合适.
一些执行递归遍历映射的映射操作可能会失败,但映射直接或间接包含自身的自引用实例除外。这包括 clone()、equals()、hashCode() 和 toString() 方法。实现可以选择性地处理自引用场景,但是大多数当前的实现都没有这样做。
此接口是 Java 集合框架的成员。
也可以看看:HashMap、TreeMap、Hashtable、SortedMap、Collection,Set
类型参数:
– 此映射维护的密钥类型
– 映射值的类型

public interface Map<k,v>

HashMap

Map接口的基于哈希表的实现。此实现提供所有可选的映射操作,并允许空值和空键。 (HashMap 类大致等同于 Hashtable,只是它是非同步的并且允许空值。)该类不保证映射的顺序;特别是,它不保证订单会随着时间的推移保持不变。
此实现为基本操作(get 和 put)提供恒定时间性能,假设散列函数在存储桶中正确分散元素。迭代集合视图需要的时间与 HashMap 实例的“容量”(桶的数量)加上它的大小(键值映射的数量)成正比。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低),这一点非常重要。
HashMap 的实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量就是哈希表创建时的容量。负载因子是衡量哈希表在其容量自动增加之前允许达到多满的指标。当哈希表中的条目数超过负载因子和当前容量的乘积时,重新哈希表(即重建内部数据结构),使哈希表具有大约两倍的桶数。
作为一般规则,默认负载因子 (.75) 在时间和空间成本之间提供了很好的权衡。较高的值会减少空间开销,但会增加查找成本(反映在 HashMap 类的大多数操作中,包括 get 和 put)。设置初始容量时应考虑映射中的预期条目数及其负载因子,以尽量减少重新哈希操作的次数。如果初始容量大于最大条目数除以负载因子,则不会发生重新哈希操作。
如果要在一个 HashMap 实例中存储许多映射,则创建具有足够大容量的映射将允许更有效地存储映射,而不是让它根据需要执行自动重新散列以增加表。请注意,使用具有相同 hashCode() 的多个键是降低任何哈希表性能的可靠方法。为了改善影响,当键是 Comparable 时,此类可以使用键之间的比较顺序来帮助打破联系。
请注意,此实现不是同步的。如果多个线程并发访问一个散列映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常是通过同步一些自然封装映射的对象来完成的.如果不存在这样的对象,则应使用 Collections.synchronizedMap 方法“包装”地图。这最好在创建时完成,以防止对地图的意外不同步访问:
Map m = Collections.synchronizedMap(new HashMap(…));
此类的所有“集合视图方法”返回的迭代器都是快速失败的:如果在迭代器创建后的任何时间对映射进行结构修改,除了通过迭代器自己的 remove 方法外,迭代器将抛出 ConcurrentModificationException .因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。

public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>,Closeable,Serializable{
}

Hashtable

这个类实现了一个哈希表,它将键映射到值。任何非空对象都可以用作键或值。
要从哈希表中成功存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。
Hashtable 的实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量就是哈希表创建时的容量。请注意,哈希表是开放的:在“哈希冲突”的情况下,单个存储桶存储多个条目,必须顺序搜索。负载因子是衡量哈希表在其容量自动增加之前允许达到多满的指标。初始容量和负载因子参数只是对实现的提示。关于何时以及是否调用 rehash 方法的确切细节取决于实现。
通常,默认负载因子 (.75) 在时间和空间成本之间提供了很好的权衡。较高的值会减少空间开销,但会增加查找条目的时间成本(这反映在大多数 Hashtable 操作中,包括 get 和 put)。
初始容量控制浪费空间和需要重新哈希操作之间的权衡,这很耗时。如果初始容量大于 Hashtable 将包含的最大条目数除以其负载因子,则不会发生重新哈希操作。但是,将初始容量设置得太高会浪费空间。
如果要将许多条目放入一个 Hashtable 中,那么创建具有足够大容量的条目可能比让它根据需要执行自动重新散列以增加表的容量更有效地插入条目。
此示例创建一个数字哈希表。它使用数字的名称作为键:

Hashtable<String, Integer> 数字
= new Hashtable<String, Integer>();
numbers.put(“one”, 1);
numbers.put(“二”, 2);
numbers.put(“三”, 3);
要检索号码,请使用以下代码:

整数 n = numbers.get(“二”);
如果 (n != null) {
System.out.println("二 = " + n);
}
该类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间对 Hashtable 进行结构修改,除了通过迭代器自己的 remove方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。 Hashtable 的键和元素方法返回的枚举不是快速失败的。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
从 Java 2 平台 v1.2 开始,该类经过改造以实现 Map 接口,使其成为 Java Collections Framework 的成员。与新的集合实现不同,Hashtable 是同步的。如果不需要线程安全的实现,建议使用 HashMap 代替 Hashtable。如果需要线程安全的高并发实现,则建议使用 java.util.concurrent.ConcurrentHashMap 代替 Hashtable。

public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>,Closeable,java.io.Serializable{
}

ConcurrentHashMap

一个哈希表,支持检索的完全并发和更新的高预期并发。该类遵循与Hashtable相同的功能规范,并包含与Hashtable的每个方法对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以防止所有访问的方式锁定整个表。在依赖其线程安全但不依赖于其同步细节的程序中,此类与 Hashtable 完全可互操作。
检索操作(包括获取)一般不会阻塞,因此可能与更新操作(包括放置和删除)重叠。检索反映了最近完成的更新操作的结果。 (更正式地说,给定键的更新操作与报告更新值的该键的任何(非空)检索具有先发生关系。)对于诸如 putAll 和 clear 之类的聚合操作,并发检索可能反映插入或删除只有一些条目。类似地,迭代器、拆分器和枚举返回反映哈希表在迭代器/枚举创建时或创建后的某个时刻的状态的元素。它们不会抛出 ConcurrentModificationException。然而,迭代器被设计为一次只能被一个线程使用。请记住,包括 size、isEmpty 和 containsValue 在内的聚合状态方法的结果通常仅在地图未在其他线程中进行并发更新时才有用。否则,这些方法的结果反映的瞬态状态可能足以用于监测或估计目的,但不适用于程序控制。
当冲突过多时(即,具有不同哈希码但以表大小为模数落入同一个槽中的键),该表动态扩展,预期平均效果是每个映射保持大约两个 bin(对应于 0.75 负载)调整大小的因子阈值)。随着映射的添加和删除,这个平均值可能会有很大差异,但总的来说,这保持了哈希表的普遍接受的时间/空间权衡。然而,调整这个或任何其他类型的哈希表的大小可能是一个相对较慢的操作。如果可能,最好将大小估计作为可选的 initialCapacity 构造函数参数提供。额外的可选 loadFactor 构造函数参数通过指定用于计算要为给定数量的元素分配的空间量的表密度,提供了一种自定义初始表容量的进一步方法。此外,为了与此类的先前版本兼容,构造函数可以选择指定预期的 concurrencyLevel 作为内部大小调整的附加提示。请注意,使用许多具有完全相同 hashCode() 的键肯定会降低任何哈希表的性能。为了改善影响,当键是 Comparable 时,此类可以使用键之间的比较顺序来帮助打破联系。
可以创建 ConcurrentHashMap 的 Set 投影(使用 newKeySet() 或 newKeySet(int)),或查看(使用 keySet(Object) 当只有键感兴趣,并且映射值(可能暂时)不使用或全部采用时)相同的映射值。
通过使用 java.util.concurrent.atomic.LongAdder 值并通过 computeIfAbsent 进行初始化,ConcurrentHashMap 可以用作可伸缩频率图(直方图或多重集的一种形式)。例如,要将计数添加到 ConcurrentHashMap<String,LongAdder> freqs,您可以使用 freqs.computeIfAbsent(k -> new LongAdder()).increment();
此类及其视图和迭代器实现了 Map 和 Iterator 接口的所有可选方法。
与 Hashtable 类似但与 HashMap 不同的是,此类不允许将 null 用作键或值。
ConcurrentHashMaps 支持一组顺序和并行的批量操作,与大多数 Stream 方法不同,这些操作被设计为安全且通常明智地应用,即使映射正在由其他线程并发更新;例如,在计算共享注册表中值的快照摘要时。共有三种操作,每种有四种形式,接受带有键、值、条目和(键,值)参数和/或返回值的函数。因为 ConcurrentHashMap 的元素没有以任何特定的方式排序,并且可能在不同的并行执行中以不同的顺序进行处理,所提供函数的正确性不应该依赖于任何排序,也不依赖于任何其他对象或值可能会暂时改变计算正在进行中;除了 forEach 操作,理想情况下应该是无副作用的。 Map.Entry 对象上的批量操作不支持 setValue 方法。
forEach:对每个元素执行给定的操作。变体形式在执行操作之前对每个元素应用给定的转换。
search:返回在每个元素上应用给定函数的第一个可用非空结果;找到结果时跳过进一步搜索。
reduce:累加每个元素。提供的归约函数不能依赖于排序(更正式地说,它应该是结合的和可交换的)。有五种变体:
普通减价。 (因为没有相应的返回类型,所以 (key, value) 函数参数没有这种方法的形式。)
累积应用于每个元素的给定函数的结果的映射归约。
使用给定的基值减少到双精度、长整数和整数的标量。
这些批量操作接受一个 parallelismThreshold 参数。如果估计当前地图大小小于给定阈值,则方法按顺序进行。使用 Long.MAX_VALUE 值会抑制所有并行性。使用值 1 可通过划分为足够多的子任务以充分利用用于所有并行计算的 ForkJoinPool.commonPool() 来实现最大并行度。通常,您最初会选择这些极值之一,然后测量使用在开销与吞吐量之间进行权衡的中间值的性能。
批量操作的并发属性遵循 ConcurrentHashMap 的并发属性:从 get(key) 和相关访问方法返回的任何非空结果都与相关的插入或更新具有先发生关系。任何批量操作的结果都反映了这些每元素关系的组成(但对于整个映射而言,不一定是原子的,除非以某种方式知道它是静止的)。相反,由于映射中的键和值永远不会为空,因此空作为当前缺少任何结果的可靠原子指示符。为了保持这个属性,null 作为所有非标量归约操作的隐式基础。对于 double、long 和 int 版本,基础应该是与任何其他值组合时返回该其他值的基础(更正式地说,它应该是归约的标识元素)。最常见的还原具有这些特性;例如,计算以 0 为基础的总和或以 MAX_VALUE 为基础的最小值。
作为参数提供的搜索和转换函数应该类似地返回 null 以指示缺少任何结果(在这种情况下不使用它)。在映射归约的情况下,这也使转换能够充当过滤器,如果元素不应该被组合,则返回 null(或者,在原始特化的情况下,身份基础)。在将它们用于搜索或归约操作之前,您可以通过在此“null 意味着现在没有任何东西”规则下自己组合它们来创建复合转换和过滤。
接受和/或返回 Entry 参数的方法维护键值关联。例如,当找到最大值的键时,它们可能很有用。请注意,可以使用 new AbstractMap.SimpleEntry(k,v) 提供“普通”条目参数。
批量操作可能会突然完成,从而引发在提供的函数的应用程序中遇到的异常。请记住,在处理此类异常时,其他并发执行的函数也可能抛出异常,或者如果第一个异常没有发生就会抛出异常。
与顺序形式相比,并行的加速是常见的,但不能保证。如果并行化计算的基础工作比计算本身更昂贵,则涉及小映射上的简短函数的并行操作可能比顺序形式执行得更慢。类似地,如果所有处理器都忙于执行不相关的任务,则并行化可能不会带来太多实际的并行性。
所有任务方法的所有参数都必须为非空。
此类是 Java 集合框架的成员。
自从:1.5
类型参数:
– 此映射维护的密钥类型
– 映射值的类型

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>,Serializable{
}

LinkedHashMap

Map接口的哈希表和链表实现,迭代顺序可预测。此实现与 HashMap 的不同之处在于它维护一个双向链表,贯穿其所有条目。这个链表定义了迭代顺序,这通常是键被插入到映射中的顺序(插入顺序)。请注意,如果将键重新插入到映射中,则插入顺序不会受到影响。 (如果当 m.containsKey(k) 在调用之前立即返回 true 时调用了 m.put(k, v),则键 k 被重新插入到映射 m 中。)
此实现使客户端免受 HashMap(和 Hashtable)提供的未指定的、通常混乱的排序的影响,而不会导致与 TreeMap 相关的成本增加。它可用于生成与原始地图具有相同顺序的地图副本,而不管原始地图的实现如何:
void foo(Map m) {
Map copy = new LinkedHashMap(m);

}

如果模块在输入上获取映射,复制它,然后返回其顺序由副本的顺序确定的结果,则此技术特别有用。 (客户通常喜欢按照呈现的顺序返回物品。)
提供了一个特殊的构造函数来创建一个链接的哈希映射,其迭代顺序是其条目上次访问的顺序,从最近最少访问到最近(访问顺序)。这种映射非常适合构建 LRU 缓存。调用 put、putIfAbsent、get、getOrDefault、compute、computeIfAbsent、computeIfPresent 或 merge 方法会导致对相应条目的访问(假设它在调用完成后存在)。如果值被替换,替换方法只会导致对条目的访问。 putAll 方法为指定映射中的每个映射生成一个条目访问,按照指定映射的条目集迭代器提供键值映射的顺序。没有其他方法生成入口访问。特别是,对集合视图的操作不会影响支持映射的迭代顺序。
removeEldestEntry(Map.Entry) 方法可能会被覆盖,以在新映射添加到地图时自动删除陈旧的映射。

此类提供所有可选的 Map 操作,并允许空元素。与 HashMap 一样,它为基本操作(添加、包含和删除)提供恒定时间性能,假设哈希函数在桶中正确分散元素。由于维护链表的额外费用,性能可能略低于 HashMap,但有一个例外:对 LinkedHashMap 的集合视图进行迭代所需的时间与映射的大小成正比,而不管其容量如何.对 HashMap 的迭代可能更昂贵,需要与其容量成正比的时间。
链接的哈希映射有两个影响其性能的参数:初始容量和负载因子。它们的定义与 HashMap 一样。但是请注意,为此类选择过高的初始容量值的惩罚不如 HashMap 严重,因为此类的迭代时间不受容量的影响。
请注意,此实现不是同步的。如果多个线程同时访问一个链接的哈希映射,并且至少有一个线程在结构上修改了映射,则它必须在外部同步。这通常是通过同步一些自然封装地图的对象来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedMap 方法“包装”地图。这最好在创建时完成,以防止对地图的意外不同步访问:
Map m = Collections.synchronizedMap(new LinkedHashMap(…));
结构修改是添加或删除一个或多个映射的任何操作,或者在访问顺序链接的哈希映射的情况下,影响迭代顺序。在插入顺序链接的哈希映射中,仅更改与映射中已包含的键关联的值不是结构修改。在按访问顺序链接的哈希映射中,仅使用 get 查询映射是一种结构修改。 )
由该类的所有集合视图方法返回的集合的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间以任何方式修改映射结构,除了通过迭代器自己的 remove 方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类的所有集合视图方法返回的集合的 spliterator 方法返回的 spliterator 是后期绑定、快速失败,并额外报告 Spliterator.ORDERED。
此类是 Java 集合框架的成员。

public calss LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{
}

TreeMap

基于红黑树的 NavigableMap 实现。地图根据其键的自然顺序进行排序,或者根据地图创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。
此实现为 containsKey、get、put 和 remove 操作提供有保证的 log(n) 时间成本。算法是对 Cormen、Leiserson 和 Rivest 的算法简介中的算法的改编。
请注意,树映射维护的排序,就像任何排序映射一样,无论是否提供显式比较器,如果此排序映射要正确实现 Map 接口,则必须与 equals 一致。 (请参阅 Comparable 或 Comparator 以获得与等于一致的精确定义。)这是因为 Map 接口是根据等于操作定义的,但排序映射使用其 compareTo(或比较)方法执行所有键比较,因此两个从排序映射的角度来看,此方法认为相等的键是相等的。排序映射的行为是明确定义的,即使它的排序与 equals 不一致;它只是不遵守 Map 接口的一般约定。
请注意,此实现不是同步的。如果多个线程同时访问一个映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与现有键关联的值不是结构修改。)这通常是通过同步一些自然封装映射的对象来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedSortedMap 方法“包装”地图。这最好在创建时完成,以防止对地图的意外不同步访问:
SortedMap m = Collections.synchronizedSortedMap(new TreeMap(…));
由该类的所有“集合视图方法”返回的集合的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间以任何方式修改了地图的结构,除了通过迭代器自己的删除方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是冒着在未来不确定的时间出现任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类中的方法及其视图返回的所有 Map.Entry 对都表示映射生成时的快照。它们不支持 Entry.setValue 方法。 (但请注意,可以使用 put 更改关联映射中的映射。)
此类是 Java 集合框架的成员。

public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Closeable.java,io.Serializable{
}

List

有序集合(也称为序列)。此界面的用户可以精确控制每个元素在列表中的插入位置。用户可以通过它们的整数索引(在列表中的位置)访问元素,并在列表中搜索元素。
与集合不同,列表通常允许重复元素。更正式地说,列表通常允许成对的元素 e1 和 e2,这样 e1.equals(e2),并且如果它们完全允许 ​​null 元素,它们通常允许多个 null 元素。有人可能希望通过在用户尝试插入它们时抛出运行时异常来实现一个禁止重复的列表,这并非不可想象,但我们希望这种用法很少见。
List 接口在迭代器、add、remove、equals 和 hashCode 方法的契约上放置了额外的规定,超出了 Collection 接口中指定的规定。为方便起见,此处还包括其他继承方法的声明。
List 接口提供了四种对列表元素进行位置(索引)访问的方法。列表(如 Java 数组)是从零开始的。请注意,对于某些实现(例如 LinkedList 类),这些操作的执行时间可能与索引值成正比。因此,如果调用者不知道实现,则迭代列表中的元素通常比通过它进行索引更可取。
List 接口提供了一个特殊的迭代器,称为 ListIterator,除了 Iterator 接口提供的正常操作之外,它允许元素插入和替换以及双向访问。提供了一种方法来获取从列表中的指定位置开始的列表迭代器。

List 接口提供了两种方法来搜索指定的对象。从性能的角度来看,应谨慎使用这些方法。在许多实现中,它们将执行代价高昂的线性搜索。
List 接口提供了两种方法来有效地在列表中的任意点插入和删除多个元素。
注意:虽然允许列表将自身包含为元素,但建议格外小心:在此类列表上不再明确定义 equals 和 hashCode 方法。
一些列表实现对它们可能包含的元素有限制。例如,有些实现禁止空元素,有些实现对其元素的类型有限制。尝试添加不合格的元素会引发未经检查的异常,通常为 NullPointerException 或 ClassCastException。尝试查询不合格元素的存在可能会引发异常,或者可能只是返回 false;一些实现会表现出前一种行为,而另一些会表现出后者。更一般地,尝试对不合格元素执行操作,其完成不会导致将不合格元素插入列表中,可能会抛出异常,或者可能会成功,具体取决于实现的选择。在此接口的规范中,此类异常被标记为“可选”。
此接口是 Java 集合框架的成员。
也可以看看:
Collection、Set、ArrayList、LinkedList、Vector、Arrays.asList(Object[])、Collections.nCopies(int、Object)、Collections.EMPTY_LIST、AbstractList、AbstractSequentialList
类型参数: – 此列表中元素的类型

public interface List<E> extends Collections<E>{
}
ArrayList

List 接口的可调整大小的数组实现。实现所有可选的列表操作,并允许所有元素,包括 null。除了实现 List 接口之外,该类还提供了操作内部用于存储列表的数组大小的方法。 (这个类大致相当于 Vector,只是它是不同步的。)
size、isEmpty、get、set、iterator 和 listIterator 操作在恒定时间内运行。 add 操作在分摊常数时间内运行,即添加 n 个元素需要 O(n) 时间。所有其他操作都在线性时间内运行(粗略地说)。与 LinkedList 实现相比,常量因子较低。
每个 ArrayList 实例都有一个容量。容量是用于存储列表中元素的数组的大小。它始终至少与列表大小一样大。随着元素被添加到 ArrayList,它的容量会自动增长。除了添加元素具有恒定的摊销时间成本之外,没有指定增长政策的细节。
应用程序可以在使用 ensureCapacity 操作添加大量元素之前增加 ArrayList 实例的容量。这可以减少增量重新分配的量。
请注意,此实现不是同步的。如果多个线程同时访问一个 ArrayList 实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步。 (结构修改是添加或删除一个或多个元素,或显式调整后备数组大小的任何操作;仅设置元素的值不是结构修改。)这通常是通过同步一些自然封装的对象来实现的。列表。如果不存在此类对象,则应使用 Collections.synchronizedList 方法“包装”该列表。这最好在创建时完成,以防止对列表的意外不同步访问:
List list = Collections.synchronizedList(new ArrayList(…));
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过迭代器自己的 remove 或 add 方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。

public class ArrayList<E> extends AbstractList<E> implements List<E>,RandomAccess,Cloneable,java.io.Serializable{
}
LinkedList

List 和 Deque 接口的双向链表实现。实现所有可选的列表操作,并允许所有元素(包括 null)。
所有操作都按双向链表的预期执行。索引到列表中的操作将从开始或结束遍历列表,以更接近指定索引的为准。
请注意,此实现不是同步的。如果多个线程并发访问一个链表,并且至少有一个线程在结构上修改了链表,则必须进行外部同步。 (结构修改是添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这通常是通过同步一些自然封装列表的对象来完成的。如果不存在这样的对象,则应使用 Collections.synchronizedList 方法“包装”该列表。这最好在创建时完成,以防止对列表的意外不同步访问:
List list = Collections.synchronizedList(new LinkedList(…));
此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间对列表进行结构修改,除了通过 Iterator 自己的 remove 或 add 方法,迭代器将抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是冒着在未来不确定的时间出现任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。
也可以看看:List,ArrayList
类型参数: – 此集合中保存的元素类型

public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>,Deque<E>,Clineable,java.io.Seralizable{
}

Set

不包含重复元素的集合。更正式地说,集合不包含一对元素 e1 和 e2,使得 e1.equals(e2),并且最多包含一个空元素。正如其名称所暗示的那样,该接口对数学集合抽象进行建模。
除了从 Collection 接口继承的那些之外,Set 接口对所有构造函数的契约以及 add、equals 和 hashCode 方法的契约进行了额外的规定。为方便起见,此处还包括其他继承方法的声明。 (这些声明随附的规范已针对 Set 接口量身定制,但不包含任何其他规定。)
对构造函数的附加规定,毫不奇怪,所有构造函数都必须创建一个不包含重复元素的集合(如上所定义)。
注意:如果将可变对象用作集合元素,则必须非常小心。如果对象的值以影响等于比较的方式更改,而对象是集合中的元素,则不会指定集合的​​行为。此禁止的一个特殊情况是不允许集合将自身包含为元素。
一些集合实现对它们可能包含的元素有限制。例如,有些实现禁止空元素,有些实现对其元素的类型有限制。尝试添加不合格的元素会引发未经检查的异常,通常为 NullPointerException 或 ClassCastException。尝试查询不合格元素的存在可能会引发异常,或者可能只是返回 false;一些实现会表现出前一种行为,而另一些会表现出后者。更一般地,尝试对不合格元素执行操作,其完成不会导致将不合格元素插入到集合中,可能会抛出异常,或者可能会成功,具体取决于实现的选择。在此接口的规范中,此类异常被标记为“可选”。
此接口是 Java 集合框架的成员。

public interface Set<E> extends Collection<E>{
}
HashSet

这个类实现了 Set 接口,由一个哈希表(实际上是一个 HashMap 实例)支持。它不保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。此类允许空元素。
此类为基本操作(添加、删除、包含和大小)提供恒定的时间性能,假设散列函数在存储桶中正确分散元素。迭代这个集合需要的时间与 HashSet 实例的大小(元素数)加上支持 HashMap 实例的“容量”(桶数)的总和成正比。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低),这一点非常重要。
请注意,此实现不是同步的。如果多个线程同时访问一个散列集,并且至少有一个线程修改了该集,则必须在外部进行同步。这通常是通过同步一些自然封装集合的对象来实现的。如果不存在这样的对象,则应使用 Collections.synchronizedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问:
Set s = Collections.synchronizedSet(new HashSet(…));
此类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间修改了集合,除了通过迭代器自己的 remove 方法之外的任何方式,迭代器都会抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Closeable,java.io.Seralizable{
}
LinkedHashSet

Set 接口的哈希表和链表实现,具有可预测的迭代顺序。此实现与 HashSet 的不同之处在于它维护一个双向链表,贯穿其所有条目。这个链表定义了迭代顺序,即元素插入到集合中的顺序(插入顺序)。请注意,如果将元素重新插入到集合中,则插入顺序不会受到影响。 (如果 s.add(e) 在 s.contains(e) 将在调用之前立即返回 true 时调用,则元素 e 被重新插入到集合 s 中。)
此实现使其客户端免受 HashSet 提供的未指定的、通常混乱的排序的影响,而不会导致与 TreeSet 相关的成本增加。它可用于生成与原始集合具有相同顺序的集合的副本,而不管原始集合的实现如何:
void foo(Set s) {
Set copy = new LinkedHashSet(s);

}

如果模块在输入上接受一个集合,复制它,然后返回其顺序由副本的顺序确定的结果,则此技术特别有用。 (客户通常喜欢按照呈现的顺序返回物品。)
此类提供所有可选的 Set 操作,并允许空元素。与 HashSet 一样,它为基本操作(添加、包含和删除)提供恒定时间性能,假设哈希函数在存储桶中正确分散元素。由于维护链表的额外费用,性能可能略低于 HashSet,但有一个例外:LinkedHashSet 上的迭代需要与集合大小成正比的时间,而不管其容量如何。对 HashSet 的迭代可能更昂贵,需要与其容量成正比的时间。
链接散列集有两个影响其性能的参数:初始容量和负载因子。它们的定义与 HashSet 一样。但是请注意,为此类选择过高的初始容量值的惩罚不如 HashSet 严重,因为此类的迭代时间不受容量的影响。
请注意,此实现不是同步的。如果多个线程同时访问一个链接的散列集,并且至少有一个线程修改了该集,则必须在外部进行同步。这通常是通过同步一些自然封装集合的对象来实现的。如果不存在这样的对象,则应使用 Collections.synchronizedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问:
Set s = Collections.synchronizedSet(new LinkedHashSet(…));
此类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间修改集合,除了通过迭代器自己的 remove 方法以外的任何方式,迭代器都会抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。

public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable,java.io.Serializable{
}
TreeSet

基于 TreeMap 的 NavigableSet 实现。元素使用它们的自然顺序进行排序,或者通过在集合创建时提供的 Comparator 进行排序,具体取决于使用的构造函数。
此实现为基本操作(添加、删除和包含)提供有保证的 log(n) 时间成本。
请注意,如果要正确实现 Set 接口,则集合维护的排序(无论是否提供显式比较器)必须与 equals 一致。 (请参阅 Comparable 或 Comparator 以获取与 equals 一致的精确定义。)这是因为 Set 接口是根据 equals 操作定义的,但是 TreeSet 实例使用它的 compareTo(或 compare)方法执行所有元素比较,所以两个被此方法视为相等的元素,从集合的角度来看,是相等的。集合的行为是明确定义的,即使它的顺序与 equals 不一致;它只是不遵守 Set 接口的一般约定。
请注意,此实现不是同步的。如果多个线程同时访问一个树集,并且至少有一个线程修改了该集,则必须在外部进行同步。这通常是通过同步一些自然封装集合的对象来实现的。如果不存在此类对象,则应使用 Collections.synchronizedSortedSet 方法“包装”该集合。这最好在创建时完成,以防止对集合的意外不同步访问:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
此类的迭代器方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间修改集合,除了通过迭代器自己的 remove 方法以外的任何方式,迭代器都会抛出 ConcurrentModificationException。因此,面对并发修改,迭代器快速而干净地失败,而不是在未来不确定的时间冒着任意、非确定性行为的风险。
请注意,无法保证迭代器的快速失败行为,因为一般而言,在存在非同步并发修改的情况下不可能做出任何硬保证。快速失败的迭代器会尽最大努力抛出 ConcurrentModificationException。因此,编写一个依赖此异常来确保其正确性的程序是错误的:迭代器的快速失败行为应该仅用于检测错误。
此类是 Java 集合框架的成员。

public class TreeSet<E> extends AbstractSet<E> implements NavigablesSet<E>, Closeable, java.io.Serializable{
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值