国外有哪些设计网站,网站被k了怎么做,263企业邮箱后缀,seo收费标准1. 集合框架概述
集合框架#xff08;Collection Framework#xff09; 是 Java 中为处理一组对象而设计的一套标准化 API#xff0c;它包括一组通用的接口、实现类和算法。这些接口和类为各种数据结构和操作方法提供了统一的实现方式#xff0c;使得开发者可以轻松地对数…1. 集合框架概述
集合框架Collection Framework 是 Java 中为处理一组对象而设计的一套标准化 API它包括一组通用的接口、实现类和算法。这些接口和类为各种数据结构和操作方法提供了统一的实现方式使得开发者可以轻松地对数据进行存储、检索和操作。
1.1 集合框架的定义与作用
定义集合框架是一套标准化的接口和类用来操作一组对象。它将各种数据结构如动态数组、链表、队列、集合等转换为 Java 中的类并为其定义统一的操作方式。
作用
简化编程集合框架提供了一组常用的数据结构和算法开发者无需重复编写基本的存储、查找、排序等操作。可扩展性通过标准接口和抽象类开发者可以轻松实现自定义的数据结构并与框架兼容。提高效率集合框架中的许多实现都是高度优化的适用于各种场景的性能需求如快速查找、增删、排序等。提高代码的可维护性集合框架通过接口将实现细节与具体数据结构分离降低了代码的耦合度方便后期维护和扩展。
1.2 集合与数组的区别
容量数组大小固定声明后无法调整集合是动态的大小可以根据需要自动调整。类型限制数组只能存储同一类型的元素基本类型或引用类型集合存储对象引用类型且可以存储不同类型的对象通过泛型可以实现类型安全。功能集合提供丰富的 API 来进行增、删、查找、遍历等操作数组的功能较为有限。
1.3 集合框架的主要接口
Collection 接口
Collection 是集合框架的根接口它定义了一组操作集合对象的方法所有集合类除 Map 之外都直接或间接实现了这个接口。常见的子接口包括
List有序集合允许元素重复如 ArrayList、LinkedList。Set无序集合不允许元素重复如 HashSet、TreeSet。Queue先进先出的队列接口如 LinkedList、PriorityQueue。Deque双端队列接口支持从两端插入、删除如 ArrayDeque。
Map 接口
Map 用于存储键值对key-value pairs不属于 Collection 接口体系但它是集合框架的核心部分之一。常见实现有
HashMap基于哈希表快速查找和插入不保证顺序。TreeMap基于红黑树按自然顺序或比较器顺序排序键。LinkedHashMap有序版本的 HashMap按插入顺序或访问顺序保持键值对。Hashtable线程安全的 HashMap效率较低。
1.4 接口与实现类
1.4.1 接口只能声明对象实例化对象由实现类通过构造函数创建 1. 只能通过接口声明一个接口类的对象
ListString list; // 仅仅声明一个接口类型的对象2. 这个接口类的对象可以接受所有接口实现类实例化的对象
list new ArrayList(); // 使用 ArrayList 实现类来创建 List 的实例3. 接口类不能实例化
ListString list new List(); // 错误接口不能直接实例化1.4.2 接口类的常用操作由实现类的对象调用
接口类中定义的方法都会被实现类进行重写当你创建了对应实现类的对象想去调用那些接口类中定义的方法实际上调用的是已经被实现类重写的方法。
ListString list new ArrayList(); // 实例化接口对象
list.add(Item 1); // 调用的是 ArrayList 实现的 add() 方法
System.out.println(list.get(0)); // 调用 ArrayList 实现的 get() 方法2. List 接口及其实现
2.1 List 概述
List 是 Java 集合框架中一个重要的接口继承自 Collection。它表示一个有序的集合允许包含重复的元素并且支持基于索引的操作能够通过索引对元素进行添加、删除和访问。
有序集合List 中的元素按插入顺序排列每个元素都有对应的索引值。允许重复元素与 Set 不同List 允许存储相同的元素。
2.2 List 的常见实现类 List是个接口不能直接实例化 故不能创建对象。要创建实例化对象必须要通过List的实现类来创建对象。 2.2.1 ArrayList
概述
ArrayList 是基于动态数组实现的 List。它是最常用的 List 实现类底层通过数组存储数据能够提供快速的随机访问。
特点
查找快由于底层是数组结构可以通过索引直接访问元素随机访问的时间复杂度为 O(1)。增删慢在中间插入或删除元素时可能需要移动大量元素因此时间复杂度为 O(n)。例如删除列表第一个元素后其他元素都需要向前移动。动态扩容当 ArrayList 容量不足时它会自动扩展容量通常为当前容量的 1.5 倍扩容操作是相对耗时的。适用场景适用于读取频繁、插入和删除较少的场景例如需要频繁遍历或随机访问元素的场景。
示例
import java.util.ArrayList;public class ArrayListExample {public static void main(String[] args) {// 创建一个 ArrayListArrayListString list new ArrayList();// 添加元素list.add(A);list.add(B);list.add(C);list.add(D);// 随机访问元素System.out.println(Element at index 1: list.get(1)); // 输出: B// 删除元素list.remove(2); // 删除索引为2的元素// 遍历列表System.out.println(ArrayList elements:);for (String element : list) {System.out.println(element);}}
}2.2.2 LinkedList
概述
LinkedList 是基于双向链表实现的 List同时实现了 Deque双端队列接口因此它不仅可以作为列表使用还可以作为队列或栈使用。
特点
增删快在链表的首尾添加或删除元素时效率很高时间复杂度为 O(1)。在中间插入或删除元素时也相对高效只需调整相关节点的指针而不需要像数组那样移动其他元素。查找慢由于链表不支持随机访问查找某个元素时需要从头或尾部遍历时间复杂度为 O(n)。适用场景适用于频繁插入和删除元素的场景例如队列、栈操作或需要频繁在集合中间添加、删除元素的场景。
示例
import java.util.LinkedList;public class LinkedListExample {public static void main(String[] args) {// 创建一个 LinkedListLinkedListString list new LinkedList();// 添加元素list.add(A);list.add(B);list.add(C);list.addFirst(First); // 在头部添加元素list.addLast(Last); // 在尾部添加元素// 删除元素list.remove(2); // 删除索引为2的元素list.removeFirst(); // 删除第一个元素list.removeLast(); // 删除最后一个元素// 遍历列表System.out.println(LinkedList elements:);for (String element : list) {System.out.println(element);}}
}2.2.3 Vector
概述
Vector 是一个线程安全的动态数组实现和 ArrayList 类似底层也是通过数组来实现的但每个操作都通过 synchronized 关键字保证了线程安全。
特点
线程安全每个方法都使用了 synchronized 关键字确保在多线程环境下的安全操作但这也带来了较大的性能开销。性能较差由于每次操作都涉及线程同步因此 Vector 的性能低于 ArrayList。在现代开发中较少使用 Vector通常用 ArrayList 并手动同步来替代。适用场景适用于需要线程安全的场景但一般不推荐使用。可以选择 ArrayList并通过显式的同步机制来实现线程安全。
示例
import java.util.Vector;public class VectorExample {public static void main(String[] args) {// 创建一个线程安全的 VectorVectorString vector new Vector();// 添加元素vector.add(A);vector.add(B);vector.add(C);// 随机访问元素System.out.println(Element at index 1: vector.get(1)); // 输出: B// 删除元素vector.remove(2); // 删除索引为2的元素// 遍历 VectorSystem.out.println(Vector elements:);for (String element : vector) {System.out.println(element);}}
}2.2.4 总结 ArrayList基于动态数组适合频繁访问元素的场景但插入、删除操作较慢。LinkedList基于双向链表适合频繁插入和删除元素的场景但随机访问较慢。Vector线程安全的动态数组实现性能较差适合多线程场景但一般用 ArrayList 加锁替代。 2.3 List 常用操作
List 提供了多种操作方法用于元素的添加、删除、访问和遍历等。 这些接口的方法都是供接口的实现类的实例化对象来调用的。 List是个接口不能实例化只能被List的实现类的对象调用。 2.3.1 添加元素
add(E e)在列表末尾添加元素。
list.add(Element);add(int index, E element)在指定索引处插入元素。
list.add(1, New Element);2.3.2 删除元素
remove(int index)删除指定索引处的元素。
list.remove(2);remove(Object o)删除列表中第一次出现的指定元素。
list.remove(Element);2.3.3 访问元素
get(int index)通过索引访问元素。
String element list.get(0);set(int index, E element)修改指定位置的元素。
list.set(2, Updated Element);2.3.4 子列表操作
subList(int fromIndex, int toIndex)返回列表中从某个索引位置fromIndex到某个索引位置toIndex的元素不包含toIndex并将这些元素组成一个新列表子列表进行返回。
ListString subList list.subList(1, 3);2.3.5 批量操作
addAll(Collection? extends E c)将另一个集合的所有元素添加到当前列表中。
ListString anotherList Arrays.asList(A, B, C);
list.addAll(anotherList);2.4 List 遍历方式
List 提供了多种遍历方式可以根据不同的需求选择合适的遍历方法。每种遍历方式都有其特点和适用场景。接下来我们详细讲解三种常见的遍历方式增强 for 循环、Iterator 和 ListIterator并通过代码示例逐一解析。
2.4.1 增强 for 循环
概述
增强 for 循环也称为 for-each 循环是一种简洁的遍历集合的方式适合不需要修改集合元素的场景。这种遍历方式的优点是代码更加简洁、易读不需要处理索引或遍历条件。
示例
import java.util.ArrayList;public class EnhancedForLoopExample {public static void main(String[] args) {// 创建一个 ArrayListArrayListString list new ArrayList();list.add(Apple);list.add(Banana);list.add(Orange);// 使用增强 for 循环遍历集合for (String element : list) {System.out.println(element);}}
}代码解释
for (String element : list) 语法简化了传统的 for 循环通过直接获取每个元素而不需要处理索引。这种方式适用于不修改集合的情况。它无法在遍历过程中对集合元素进行增删操作。增强 for 循环背后实际上使用了 Iterator但语法更加简洁。 2.4.2 Iterator 遍历
概述
Iterator 是 List 提供的一种标准遍历方式适合需要在遍历时修改删除集合元素的情况。Iterator 可以通过 hasNext() 判断是否有下一个元素通过 next() 获取当前元素并可以通过 remove() 删除当前元素。
示例
import java.util.ArrayList;
import java.util.Iterator;public class IteratorExample {public static void main(String[] args) {// 创建一个 ArrayListArrayListString list new ArrayList();list.add(Apple);list.add(Banana);list.add(Orange);// 获取 Iterator 对象IteratorString iterator list.iterator();// 使用 Iterator 遍历集合while (iterator.hasNext()) {String element iterator.next();System.out.println(element);// 删除元素 Bananaif (element.equals(Banana)) {iterator.remove(); // 通过 iterator 删除当前元素}}// 遍历后的集合内容System.out.println(After removal: list);}
}代码解释
iterator()通过 list.iterator() 方法获取 Iterator 对象用于遍历集合。hasNext()判断集合中是否还有未遍历的元素。next()获取当前元素并将游标移动到下一个元素。remove()通过 Iterator 删除当前元素。注意只能在调用 next() 后调用 remove()否则会抛出异常。Iterator 的主要优势是可以在遍历时安全地删除集合中的元素而不会抛出 ConcurrentModificationException 异常。这在需要在遍历时修改集合的场景下非常有用。 2.4.3 ListIterator 遍历
概述
ListIterator 是 Iterator 的增强版专门用于 List 集合。它不仅支持像 Iterator 一样的正向遍历还支持双向遍历。此外它还允许在遍历过程中修改集合如添加、删除或替换元素这是 Iterator 无法提供的功能。
示例
import java.util.LinkedList;
import java.util.ListIterator;public class ListIteratorExample {public static void main(String[] args) {// 创建一个 LinkedListLinkedListString list new LinkedList();list.add(Apple);list.add(Banana);list.add(Orange);// 获取 ListIterator 对象ListIteratorString listIterator list.listIterator();// 正向遍历集合System.out.println(Forward traversal:);while (listIterator.hasNext()) {String element listIterator.next();System.out.println(element);// 在元素 Banana 之后插入一个新元素 Grapesif (element.equals(Banana)) {listIterator.add(Grapes);}}// 反向遍历集合System.out.println(Backward traversal:);while (listIterator.hasPrevious()) {String element listIterator.previous();System.out.println(element);}}
}代码解释
listIterator()通过 list.listIterator() 方法获取 ListIterator 对象它允许正向和反向遍历。hasNext() 和 next()正向遍历时使用这些方法来获取下一个元素。hasPrevious() 和 previous()反向遍历时使用这些方法来获取上一个元素。add()允许在遍历过程中插入新元素而不会破坏遍历流程。ListIterator 的主要优势是可以在遍历过程中添加、删除或替换元素同时支持双向遍历。这使得它在复杂的修改场景中非常有用比如需要在遍历过程中灵活插入或删除元素。
2.4.4 总结 增强 for 循环语法简洁适合只读遍历不适合在遍历过程中修改集合。Iterator适合在遍历过程中删除元素不能反向遍历或在遍历时插入新元素。ListIterator支持双向遍历允许在遍历过程中添加、删除或替换元素功能比 Iterator 更强大。 3. Set 接口及其实现
3.1 Set 概述
Set 是 Java 集合框架中的一个接口继承自 Collection。它代表一个无序的集合其中的元素不能重复。这意味着 Set 中的每个元素都是唯一的并且 Set 不维护元素的插入顺序除了一些特殊实现类如 LinkedHashSet。Set 适合用于去重操作和需要集合运算如并集、交集等的场景。
无序集合Set 中的元素没有固定顺序具体的排序取决于 Set 的具体实现。不允许重复元素在 Set 中每个元素都是唯一的如果试图向 Set 中添加一个已经存在的元素则插入操作会被忽略。 3.2 Set 的常见实现类
Set 接口有多个常见的实现类它们的底层数据结构不同因此在性能和适用场景上各有差异。常见的实现类包括 HashSet、LinkedHashSet 和 TreeSet。
3.2.1 HashSet 概述HashSet 是基于哈希表实现的 Set元素存储在哈希表中因此没有固定的顺序。HashSet 提供了高效的查找和插入操作。 特点 无序HashSet 不保证元素的插入顺序。插入的元素位置是由其哈希值决定的因此每次遍历时元素顺序可能不同。允许 null 值HashSet 可以存储 null但只能存储一个 null 值因为 Set 不允许重复元素。查找和插入性能较好由于底层是哈希表查找和插入的时间复杂度为 O(1)非常高效。 适用场景适用于不关心元素顺序、只需确保元素唯一且需要高效查找和插入的场景。
代码示例
import java.util.HashSet;public class HashSetExample {public static void main(String[] args) {// 创建一个 HashSetHashSetString set new HashSet();// 添加元素set.add(Apple);set.add(Banana);set.add(Orange);set.add(Banana); // 重复元素不会被添加// 允许存储一个 null 值set.add(null);// 遍历集合for (String element : set) {System.out.println(element);}}
}代码解释
HashSet 是无序的所以每次遍历时元素的顺序可能不同。尝试添加重复的元素时不会抛出异常但重复的元素不会再次添加到集合中。 3.2.2 LinkedHashSet 概述LinkedHashSet 是基于哈希表和链表实现的 Set它与 HashSet 的不同之处在于它维护了元素的插入顺序即元素会按照插入的顺序进行存储和遍历。 特点 有序LinkedHashSet 保留了元素的插入顺序在遍历时按元素插入的顺序进行。允许 null 值与 HashSet 一样LinkedHashSet 允许存储 null 值但只能存储一个 null。查找和插入性能较好性能略低于 HashSet因为维护了链表以存储插入顺序但查找和插入的时间复杂度依然是 O(1)。 适用场景适用于需要保证元素的插入顺序并且需要进行快速查找和插入的场景。
代码示例
import java.util.LinkedHashSet;public class LinkedHashSetExample {public static void main(String[] args) {// 创建一个 LinkedHashSetLinkedHashSetString set new LinkedHashSet();// 添加元素set.add(Apple);set.add(Banana);set.add(Orange);set.add(Banana); // 重复元素不会被添加// 遍历集合按插入顺序for (String element : set) {System.out.println(element);}}
}代码解释
LinkedHashSet 保留了元素的插入顺序因此遍历时输出的顺序与插入顺序一致。 3.2.3 TreeSet 概述TreeSet 是基于红黑树实现的 Set它保证了集合中元素的自然顺序或者通过提供的 Comparator 进行定制排序。由于底层是平衡二叉树TreeSet 的查找、插入和删除操作的时间复杂度为 O(log n)。 特点 有序TreeSet 保证元素按照自然顺序如数字从小到大、字符串按字典顺序进行存储和遍历。如果需要自定义排序则可以通过构造 TreeSet 时提供 Comparator 实现。不允许 null 值TreeSet 不允许存储 null因为 TreeSet 需要对元素进行排序而 null 值无法进行排序操作。查找和插入性能较好基于红黑树插入、删除、查找的时间复杂度为 O(log n)适合需要有序存储和快速查找的场景。定制排序可以通过在创建 TreeSet 时传入 Comparator 对象来自定义排序规则。 适用场景适用于需要对元素进行自然排序或自定义排序的场景特别适合有序集合操作。
代码示例
import java.util.TreeSet;public class TreeSetExample {public static void main(String[] args) {// 创建一个 TreeSetTreeSetString set new TreeSet();// 添加元素自动按自然顺序排序set.add(Banana);set.add(Apple);set.add(Orange);// 遍历集合按自然顺序for (String element : set) {System.out.println(element);}}
}代码解释
TreeSet 会按照字典顺序对字符串进行排序因此遍历时输出的顺序为 Apple、Banana、Orange。
使用 Comparator 进行定制排序
1. 你需要先定义一个Comparator
ComparatorString lengthComparator就定义了一个比较String类型的名叫lengthComparator的Comparator。
2. 重写 compare() 方法
你需要重写新创建的 Comparator 中的 compare() 方法该方法通过比较传入的两个参数并根据返回值确定这两个参数的顺序类似于逐对比较集合中的所有元素通过 compare() 方法的返回值来确定最终的排序
在 compare(T o1, T o2) 方法中定义你希望的比较逻辑
返回负值表示 o1 应该排在 o2 之前。返回正值表示 o1 应该排在 o2 之后。返回 0表示 o1 和 o2 在排序中视为相等顺序不变。
3. 将 Comparator 应用于集合
通过代码TreeSetString set new TreeSet(lengthComparator);可以将你自定义的名为lengthComparator的Comparator应用于集合。
示例 按字符串长度排序
假设我们要按字符串长度排序而不是默认的字母顺序。我们可以创建一个自定义的 Comparator
import java.util.Comparator;
import java.util.TreeSet;public class CustomComparatorExample {public static void main(String[] args) {// 定义自定义 Comparator按字符串长度排序ComparatorString lengthComparator new ComparatorString() {Overridepublic int compare(String s1, String s2) {// 比较两个字符串的长度return Integer.compare(s1.length(), s2.length());}};// 使用自定义 Comparator 创建 TreeSetTreeSetString set new TreeSet(lengthComparator);set.add(Banana);set.add(Apple);set.add(Orange);set.add(Kiwi);// 输出结果按字符串长度排序for (String s : set) {System.out.println(s);}}
}Integer.compare(s1.length(), s2.length()) 用于比较两个字符串的长度。返回负值时s1.length() s2.length()表示 s1 排在 s2 之前。返回正值时s1.length() s2.length()表示 s1 排在 s2 之后。返回 0 时表示长度相同按自然顺序或保留插入顺序。 3.2.4 总结 HashSet基于哈希表提供无序的集合允许存储 null性能高效。LinkedHashSet基于哈希表和链表保留插入顺序适合需要有序遍历的场景。TreeSet基于红黑树提供按自然顺序或自定义顺序排序的有序集合不允许 null 值。 3.3 Set 常用操作
Set 提供了一些常见的集合操作除了 Collection 接口定义的基本操作外Set 还可以进行一些集合运算如交集、并集和差集。
3.3.1 添加元素
add(E e)将元素添加到 Set 中如果元素已经存在则不会添加。
set.add(Apple);3.3.2 删除元素
remove(Object o)删除 Set 中指定的元素。
set.remove(Apple);3.3.3 判断元素是否存在
contains(Object o)判断 Set 中是否包含指定元素。
boolean exists set.contains(Apple);3.3.4 集合运算
交集
retainAll(Collection? c)保留当前 Set 中与另一个集合相同的元素。
set1.retainAll(set2); // 计算 set1 和 set2 的交集并集
addAll(Collection? extends E c)将另一个集合的所有元素添加到当前 Set 中。
set1.addAll(set2); // 计算 set1 和 set2 的并集差集
removeAll(Collection? c)从当前 Set 中删除所有在另一个集合中出现的元素。
set1.removeAll(set2); // 计算 set1 和 set2 的差集retainAll()计算两个集合的交集保留 set1 和 set2 的共同元素。addAll()计算两个集合的并集将 set2 中的元素添加到 set1 中。removeAll()计算两个集合的差集从 set1 中移除 set2 中存在的元素。 4. Map 接口及其实现
4.1 Map 概述
Map 是一个用于存储键值对key-value pairs的集合接口。与其他集合类型不同Map 是通过键key来映射到对应的值value并且每个键在 Map 中是唯一的。
键在 Map 中每个键是唯一的不能重复。如果尝试添加相同的键新值将会覆盖旧值。值与键关联的对象可以重复。多个不同的键可以映射到相同的值。键值对一个键和一个值共同组成一个键值对这个键值对在 Map 中作为一个整体元素进行存储。 4.2 常见的 Map 实现类
4.2.1 HashMap 概述HashMap 是最常用的 Map 实现类基于哈希表Hash Table实现能够提供快速的键值对存储和查找。 特点 无序HashMap 不保证键值对的存储顺序插入和遍历时顺序可能不同。允许 null 键和 null 值HashMap 允许一个 null 键和多个 null 值。性能高效由于哈希表的底层实现查找、插入和删除的时间复杂度为 O(1)适合大规模数据的处理。 适用场景适用于需要通过键快速存取数据但不关心数据顺序的场景。
示例
HashMapString, String hashMap new HashMap();
hashMap.put(username, john_doe);
hashMap.put(email, johnexample.com);
String value hashMap.get(username);4.2.2 LinkedHashMap 概述LinkedHashMap 是 HashMap 的有序版本内部使用哈希表和双向链表结合的方式实现能够维护键值对的插入顺序或访问顺序。 特点 按插入顺序排序LinkedHashMap 默认按照键值对插入的顺序存储和遍历。允许 null 键和 null 值与 HashMap 类似允许一个 null 键和多个 null 值。支持按访问顺序排序可以通过构造方法指定 LinkedHashMap 为按访问顺序排序每次访问如 get() 操作都会将键值对移到末尾。 适用场景适用于需要维护键值对顺序的场景尤其是在插入顺序或访问顺序相关的场景。
示例
LinkedHashMapString, String linkedHashMap new LinkedHashMap();
linkedHashMap.put(username, john_doe);
linkedHashMap.put(email, johnexample.com);
String value linkedHashMap.get(username);如果你希望每次访问如 get() 操作都会将键值对移到末尾则需要使用如下的构造函数来创建LinkedHashMap。 LinkedHashMapString, String linkedHashMap new LinkedHashMap(16, 0.75f, true);三个参数分别是初始容量、负载因子、是否按访问顺寻排序 4.2.3 TreeMap 概述TreeMap 基于红黑树Red-Black Tree实现能够保证键值对按照键的自然顺序或通过 Comparator 进行定制排序。 特点 按键排序TreeMap 会根据键的自然顺序进行排序如数字从小到大、字符串按字母顺序。支持自定义排序可以通过 Comparator 定制键的排序规则。不允许 null 键由于键需要排序TreeMap 不允许存储 null 键但允许 null 值。 适用场景适用于需要对键值对进行排序存储的场景尤其是根据键的自然顺序或定制顺序进行排序的需求。
示例
TreeMapString, String treeMap new TreeMap();
treeMap.put(username, john_doe);
treeMap.put(email, johnexample.com);
String value treeMap.get(username);4.2.4 ConcurrentHashMap 概述ConcurrentHashMap 是 HashMap 的线程安全版本专为高并发环境设计。它通过分段锁机制提高了并发性能允许多个线程同时对 ConcurrentHashMap 进行操作。 特点 线程安全ConcurrentHashMap 使用分段锁segment locking确保线程安全但只在需要的部分加锁允许高效的并发读写。不允许 null 键和 null 值与 Hashtable 类似ConcurrentHashMap 不允许 null 键或 null 值。性能较好相比于传统的 HashtableConcurrentHashMap 在多线程场景下具有更好的性能。 适用场景适用于多线程环境中需要线程安全的键值对存储操作同时具有较高并发性能的场景。
示例
ConcurrentHashMapString, String concurrentHashMap new ConcurrentHashMap();
concurrentHashMap.put(username, john_doe);
concurrentHashMap.put(email, johnexample.com);
String value concurrentHashMap.get(username);这里所实现的线程安全使用分段锁是自动实现的它通过判断读操作不需要加锁写操作需要加锁来自动进行不需要再代码层面显式操作。 4.2.5 总结 HashMap基于哈希表实现键值无序允许 null 键和 null 值性能高效。LinkedHashMap基于哈希表和链表实现按插入顺序或访问顺序排序允许 null 键和 null 值。TreeMap基于红黑树实现按键的自然顺序排序或通过 Comparator 定制排序不允许 null 键。ConcurrentHashMap线程安全的 HashMap使用分段锁机制提高了多线程环境下的性能不允许 null 键和 null 值。 4.3 Map 常用操作
Map 提供了一些基础的操作方法用于存储、删除、访问和遍历键值对。
4.3.1 添加键值对
put(K key, V value)将一个键值对插入到 Map 中。如果键已经存在则替换旧值。
map.put(username, john_doe);4.3.2 删除键值对
remove(Object key)根据键删除对应的键值对。
map.remove(username);4.3.3 访问键值对
get(Object key)根据键获取对应的值。如果键不存在返回 null。
String value map.get(username);4.3.4 判断是否包含键或值
containsKey(Object key)检查 Map 是否包含指定的键。
containsValue(Object value)检查 Map 是否包含指定的值。
boolean hasKey map.containsKey(username);
boolean hasValue map.containsValue(john_doe);4.3.5 获取键、值或键值对集合
keySet()返回 Map 中所有键的集合SetK。
values()返回 Map 中所有值的集合CollectionV。
entrySet()返回 Map 中所有键值对的集合SetMap.EntryK, V。
SetString keys map.keySet(); // 获取所有键
CollectionString values map.values(); // 获取所有值
SetMap.EntryString, String entries map.entrySet(); // 获取所有键值对Map.EntryK, V 是 Map 接口的一个内部静态接口表示 Map 中的一个键值对key-value pair。它用来封装 Map 中的键K和值V作为一个完整的对象。这里要用SetMap.EntryString, String集合声明对象的原因是因为map.entrySet()就返回的是一个键值对的Set的集合Set集合的内部是一个个单独的键值对所以这里要用Map.EntryString, String作为Set集合中的元素类型。 4.4 遍历 Map
Map 可以通过多种方式遍历其键值对
4.4.1 遍历键集合keySet()
通过 keySet() 获取所有键然后通过键访问对应的值
for (String key : map.keySet()) {System.out.println(Key: key , Value: map.get(key));
}4.4.2 遍历值集合values()
通过 values() 获取所有值并进行遍历
for (String value : map.values()) {System.out.println(Value: value);
}4.4.3 遍历键值对集合entrySet()
使用 entrySet() 获取所有键值对并直接遍历
for (Map.EntryString, String entry : map.entrySet()) {System.out.println(Key: entry.getKey() , Value: entry.getValue());
}Map.EntryString, String entry声明的是一个单独的键值对不是一个键值对集合。 5. Queue 和 Deque 接口及其实现
5.1 Queue 概述
Queue队列是 Java 中用于处理先进先出FIFOFirst-In-First-Out操作的集合接口。队列中的元素按插入顺序排列最早插入的元素最先被处理。Queue 接口扩展了 Collection 接口并定义了一些特定于队列的操作方法。Deque双端队列是 Queue 的扩展允许在队列两端进行元素插入和删除操作。
Queue适用于按顺序处理元素的场景例如任务调度、消息处理。Deque支持从两端插入和删除元素可以作为队列FIFO或栈LIFO后进先出使用。 5.2 Queue 和 Deque 的常见实现类
5.2.1 LinkedList 概述LinkedList 是双向链表的实现类既实现了 Queue 接口也实现了 Deque 接口。因此它支持队列操作先进先出同时也支持双端队列和栈操作后进先出。 特点 既可以作为标准的队列使用也可以作为双端队列并提供了栈操作方法。插入和删除操作的效率较高适合频繁增删操作的场景。 适用场景适合需要同时支持队列、双端队列和栈操作的场景。
示例
DequeString deque new LinkedList();// 双端队列操作从队首和队尾插入元素
deque.offerFirst(Item 1); // 从队首插入
deque.offerLast(Item 2); // 从队尾插入// 移除元素
System.out.println(deque.pollFirst()); // 输出 Item 1从队首移除
System.out.println(deque.pollLast()); // 输出 Item 2从队尾移除// 栈操作后进先出LIFO
deque.push(Item 3); // 压栈
System.out.println(deque.pop()); // 出栈输出 Item 3双端队列操作通过 offerFirst() 和 offerLast() 可以分别从队首和队尾插入元素通过 pollFirst() 和 pollLast() 可以分别从队首和队尾移除元素。栈操作通过 push() 实现压栈通过 pop() 实现后进先出LIFO的出栈操作。 5.2.2 PriorityQueue 概述PriorityQueue 是基于优先级堆实现的队列元素按优先级排序而不是插入顺序。默认情况下它使用自然顺序最小的元素优先也可以通过自定义的 Comparator 实现定制的排序规则。 特点 元素按优先级排序队列头部是优先级最高的元素默认是最小的元素。PriorityQueue 不允许存储 null 元素。 适用场景适用于需要根据优先级处理元素的场景如任务调度、事件处理。
示例
// 自定义 Comparator 实现优先级由大到小排序降序
PriorityQueueInteger priorityQueue new PriorityQueue(new ComparatorInteger() {Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1; // 降序o2 比 o1 大o2 优先级更高}
});priorityQueue.offer(5);
priorityQueue.offer(1);
priorityQueue.offer(3);System.out.println(priorityQueue.poll()); // 输出 5优先级最高的元素
System.out.println(priorityQueue.poll()); // 输出 3
System.out.println(priorityQueue.poll()); // 输出 1自定义 Comparator通过 PriorityQueue 的构造函数传入 Comparator可以定制元素的排序规则。此例中通过 Comparator 实现降序排序优先级从大到小排列。如果不自主定义Comparator则是按升序排序。 5.2.3 ArrayDeque 概述ArrayDeque 是基于数组实现的双端队列既可以用作队列也可以用作栈。它提供了高效的双端队列操作相比 LinkedListArrayDeque 的内存开销更小操作速度更快。 特点 无界双端队列ArrayDeque 没有固定大小可以根据需要动态扩展。高效的队列和栈操作它的双端操作和栈操作比 LinkedList 更加高效因为它基于数组实现。 适用场景适用于需要频繁从两端操作元素的场景或者需要高效的栈操作。
示例
DequeString arrayDeque new ArrayDeque();// 双端队列操作
arrayDeque.offerFirst(Item 1); // 从队首插入
arrayDeque.offerLast(Item 2); // 从队尾插入System.out.println(arrayDeque.pollFirst()); // 输出 Item 1从队首移除
System.out.println(arrayDeque.pollLast()); // 输出 Item 2从队尾移除// 栈操作后进先出
arrayDeque.push(Item 3); // 压栈
System.out.println(arrayDeque.pop()); // 出栈输出 Item 3双端队列操作通过 offerFirst() 和 offerLast() 从两端插入元素pollFirst() 和 pollLast() 从两端移除元素。栈操作使用 push() 进行压栈操作使用 pop() 进行后进先出的栈操作。 5.3 Queue 和 Deque 常用操作
Queue 和 Deque 提供了许多常用的操作方法这些方法可用于队列操作FIFO或栈操作LIFO根据场景选择不同的实现类。以下是一些常见操作方法
5.3.1 入队操作
offer(E e)将元素插入到队列的尾部如果队列已满返回 false。不同于 add()offer() 不会抛出异常。
queue.offer(Item);5.3.2 出队操作
poll()从队列头部移除并返回元素如果队列为空返回 null。不同于 remove()poll() 不会抛出异常。
queue.poll();5.3.3 查看队首元素
peek()查看队列头部的元素但不移除。如果队列为空返回 null。
queue.peek();5.3.4 栈操作
push(E e)将元素压入栈作为栈顶元素。
deque.push(Item);pop()弹出栈顶元素并返回它如果栈为空则抛出异常。
deque.pop();5.3.5 处理阻塞队列BlockingQueue
BlockingQueue 是 Queue 的一种特殊实现常用于多线程环境下的生产者-消费者模型。BlockingQueue 支持线程安全的操作在队列为空时阻塞获取操作在队列已满时阻塞插入操作。
ArrayBlockingQueue基于数组的有界阻塞队列队列大小固定。LinkedBlockingQueue基于链表的阻塞队列可以指定大小也可以不指定默认无界。
BlockingQueueString blockingQueue new ArrayBlockingQueue(10);
blockingQueue.put(Item 1); // 阻塞插入
String item blockingQueue.take(); // 阻塞获取6. 集合工具类
在 Java 中Collections 和 Arrays 工具类极大地简化了对集合和数组的常用操作。它们提供了排序、搜索、同步化等功能方便开发者对集合或数组进行常规处理。接下来针对一些常见的操作方法我们做详细解释和代码示例并纠正部分内容。 6.1 Collections 类
Collections 是一个静态工具类用于操作集合。它包含了排序、搜索、同步化等常用方法。所有方法都是静态的无需创建 Collections 实例即可使用。一般来说更多使用于List集合
6.1.1 常用方法
sort(ListT list)对 List 集合进行排序。如果元素实现了 Comparable 接口可以按照自然顺序排序。如果传入了 Comparator则按照自定义的规则进行排序。
自然排序
自然排序要求 List 中的元素实现了 Comparable 接口。Comparable 定义了默认的排序方式例如字母或数字的升序排列。
ListInteger list Arrays.asList(5, 1, 3, 8, 2);
Collections.sort(list); // 对 list 进行自然排序
System.out.println(list); // 输出 [1, 2, 3, 5, 8]自定义排序规则使用 Comparator
你可以传入自定义的 Comparator用于自定义排序规则。Comparator 是一个函数接口允许你根据需要定义比较逻辑。
ListInteger list Arrays.asList(5, 1, 3, 8, 2);// 使用 Comparator 实现降序排序
Collections.sort(list, (a, b) - b - a); // 按降序排列
System.out.println(list); // 输出 [8, 5, 3, 2, 1]在这个示例中Comparator 通过 lambda 表达式定义了比较规则b - a这意味着 b 的优先级高于 a从而实现降序排序。 binarySearch(ListT list, T key)使用二分查找法查找 List 中的元素。要求 List 必须已经按升序排序否则结果不可预期。
ListInteger list Arrays.asList(1, 2, 3, 5, 8);
int index Collections.binarySearch(list, 3); // 查找元素 3
System.out.println(index); // 输出 2如果 List 没有按照升序排列binarySearch() 会返回错误的结果。因此确保在调用 binarySearch() 之前List 已经被排序。 reverse(List? list)将 List 中的元素顺序反转。
ListString list Arrays.asList(A, B, C, D);
Collections.reverse(list);
System.out.println(list); // 输出 [D, C, B, A]shuffle(List? list)将 List 中的元素随机打乱顺序。
ListInteger list Arrays.asList(1, 2, 3, 4, 5);
Collections.shuffle(list); // 随机打乱元素顺序
System.out.println(list); // 输出可能是 [3, 5, 2, 1, 4]synchronizedList(ListT list)将一个 List 变为线程安全的 List。其他集合类型如 Set 和 Map 也有类似的同步化方法如 synchronizedSet() 和 synchronizedMap()。
ListString list new ArrayList();
ListString synchronizedList Collections.synchronizedList(list);synchronized (synchronizedList) {synchronizedList.add(Item 1);
}fill(List? super T list, T obj)用指定的元素替换 List 中的所有元素。例如将所有元素替换为 Z
ListString list Arrays.asList(A, B, C);
Collections.fill(list, Z); // 将所有元素替换为 Z
System.out.println(list); // 输出 [Z, Z, Z]6.2 Arrays 类
Arrays 是用于操作数组的工具类。它提供了数组转换、排序、搜索等功能方便对数组进行各种操作。Arrays 类中的方法类似于 Collections但它专门用于处理数组。
6.2.1 常用方法
asList(T... a)将一个数组转换为 List 集合。注意此方法返回的 List 是固定大小的不能添加或删除元素但可以修改已有的元素。
String[] array {A, B, C};
ListString list Arrays.asList(array);
System.out.println(list); // 输出 [A, B, C]sort(T[] a)对数组进行自然排序。如果是对象数组数组中的对象必须实现 Comparable 接口。
int[] array {5, 3, 8, 1, 2};
Arrays.sort(array); // 对数组进行升序排序
System.out.println(Arrays.toString(array)); // 输出 [1, 2, 3, 5, 8]binarySearch(T[] a, T key)在排序的数组中使用二分查找法查找元素的索引。
int[] array {1, 2, 3, 5, 8};
int index Arrays.binarySearch(array, 3); // 查找元素 3 的索引
System.out.println(index); // 输出 2类似于 Collections.binarySearch()Arrays.binarySearch() 也要求数组必须是升序排列的否则结果不可预期。 equals(T[] a, T[] b)比较两个数组是否相等。数组中的元素必须一一对应相等。
int[] array1 {1, 2, 3};
int[] array2 {1, 2, 3};
boolean isEqual Arrays.equals(array1, array2);
System.out.println(isEqual); // 输出 truetoString(T[] a)将数组转换为字符串便于输出数组内容。
int[] array {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(array)); // 输出 [1, 2, 3, 4, 5]6.3 总结
Collections 类
排序sort() 对 List 进行自然排序或自定义排序。搜索binarySearch() 需要集合已排序使用二分查找法查找元素。修改顺序reverse() 反转元素顺序shuffle() 随机打乱顺序。同步化synchronizedList() 将 List 包装为线程安全集合。其他操作如 fill() 用指定值替换 List 中的所有元素max() 返回最大元素。
Arrays 类
转换asList() 将数组转换为 List。排序和搜索sort() 对数组进行排序binarySearch() 在排序数组中查找元素。实现 Comparable 接口如果数组中的对象需要排序必须实现 Comparable 接口并提供 compareTo() 方法。其他操作equals() 比较两个数组是否相等toString() 打印数组内容。
7. 集合框架的性能与优化
7.1 集合类的选择
在实际开发中选择合适的集合类是性能优化的关键。下面是不同场景下如何选择合适的集合类的指南
1. 快速访问元素ArrayList 和 HashMap 是理想选择能够提供 O(1) 的读操作。
ArrayList适用于需要频繁随机访问元素的场景例如缓存、索引。HashMap适用于快速查找键值对的场景例如缓存键值对数据。
2. 频繁插入和删除LinkedList 和 HashSet 是合适的选择。
LinkedList适用于频繁在头部或中间插入/删除元素的场景例如队列或双端队列。HashSet适用于频繁插入、删除且无需排序的场景且需要确保元素唯一。
3. 需要排序的集合选择基于排序的集合类如 TreeSet、TreeMap。
TreeSet 和 TreeMap适用于需要对集合中的元素或键值对进行有序存储的场景。
4. 多线程环境选择线程安全的集合类如 ConcurrentHashMap、Collections.synchronizedList()。
ConcurrentHashMap适用于高并发情况下的键值对存储。Collections.synchronizedList()通过同步包装的线程安全集合。
7.2 如何优化集合的性能
优化集合的性能可以通过合理设置集合的初始容量减少不必要的扩容操作和复制操作。以下是两个主要的优化方向
7.2.1 初始化容量设置与避免多次扩容操作导致复制
集合类如 ArrayList 和 HashMap 在底层是基于动态数组实现的。当集合中的元素超过当前容量时会自动扩容通常扩容为原来容量的 1.5 倍。每次扩容都会创建一个新的更大数组并将旧数组的元素复制到新数组中这个过程会产生大量内存分配和元素复制的开销特别是在大量数据插入时性能影响显著。
优化建议
ArrayList在创建 ArrayList 时可以通过构造函数指定初始容量避免扩容导致的性能开销。
ListString list new ArrayList(100); // 初始化容量为 100HashMap同样可以通过构造函数指定初始容量和负载因子以减少扩容带来的性能问题。
MapString, Integer map new HashMap(100, 0.75f); // 初始容量为 100负载因子为 0.75100是初始容量初始容量是指在初始化时分配的哈希表的初始大小。如果你预估有大量数据要存储可以适当增加这个值以避免哈希表频繁扩容的开销。0.75f是负载因子负载因子是一个衡量哈希表在自动扩容之前允许多大比例的空间可以被使用的参数。负载因子 0.75 表示当哈希表中已使用的空间达到总容量的 75% 时会自动扩容通常是容量翻倍以保持查找效率。如果你想减少扩容次数可以设置一个较大的负载因子但这可能会导致查找性能下降。 7.2.2 避免重复的集合转换操作
在开发中频繁地在不同集合类型如 List 和 Set之间转换会导致不必要的性能损耗因为每次转换都需要遍历集合并复制所有元素。这种操作在大数据量的场景下尤其影响性能。
优化建议 在选择集合类型时尽量避免后期频繁的集合转换操作。比如如果需要保证元素的唯一性直接使用 Set 初始化集合而不是先用 List然后再转换为 Set。
8. 线程安全的集合
在多线程环境下集合类的使用需要格外注意因为标准的集合类如 ArrayList、HashMap 等并不具备线程安全的特性。在多个线程并发访问或修改这些集合时可能会导致数据不一致甚至引发程序崩溃。Java 提供了几种不同方式来保证集合的线程安全性主要分为同步集合和并发集合框架。
8.1 同步集合与并发集合的区别 同步集合通过同步synchronized机制来保证线程安全通常会锁定整个集合操作保证同一时刻只有一个线程可以修改集合。这种方法虽然能保证线程安全但性能较低尤其在高并发场景下多个线程竞争同一锁时会导致性能瓶颈。 并发集合并发集合框架java.util.concurrent 包提供了一些集合类它们使用更加精细的锁机制甚至无锁机制来提高并发场景下的性能。这些集合类支持高效的并发访问减少线程间的争用适用于高并发环境。 8.2 同步集合
同步集合是通过 Collections.synchronizedXXX() 方法对现有的非线程安全集合进行同步包装。所有的集合操作都会被加锁确保同一时间只有一个线程能访问集合。虽然这保证了线程安全但由于每次操作都需要加锁和解锁性能较低尤其在写操作频繁时竞争锁的开销较大。
8.2.1 Collections.synchronizedList()
将 List 集合同步化保证其在线程并发访问时的安全性。适合不太频繁的并发访问场景。
示例
ListString list new ArrayList();
ListString synchronizedList Collections.synchronizedList(list);synchronized (synchronizedList) {synchronizedList.add(Item 1); // 在同步代码块中进行操作
}注意在迭代 synchronizedList 时必须手动在外层加上 synchronized 块确保整个迭代过程的线程安全性。
8.2.2 Collections.synchronizedMap()
将 Map 集合同步化保证并发情况下的安全性。
示例
MapString, Integer map new HashMap();
MapString, Integer synchronizedMap Collections.synchronizedMap(map);synchronized (synchronizedMap) {synchronizedMap.put(key1, 1); // 在同步代码块中进行操作
}8.2.3 同步集合的缺点
性能瓶颈同步集合使用全局锁每次访问集合时需要获取锁这意味着多个线程同时访问时会有锁竞争和阻塞导致性能下降。适用场景同步集合适合低并发场景或写操作较少、读操作较多的情况。对于高并发场景使用并发集合框架更加合适。 8.3 并发集合框架
并发集合框架java.util.concurrent为多线程环境提供了高效、线程安全的集合类。这些类通过更复杂的机制如分段锁或无锁算法来提高在高并发场景下的性能。与同步集合相比并发集合框架中的集合类具有更细粒度的锁定机制能够支持更高的并发访问。
8.3.1 ConcurrentHashMap 概述ConcurrentHashMap 是 HashMap 的线程安全版本它采用分段锁机制Segmented Locking将整个哈希表分为多个段每个段有独立的锁这样多个线程可以同时访问不同段的哈希表从而提高并发性能。 特点 线程安全适用于高并发环境。支持高效的读写操作避免了传统同步集合中的全局锁。读取操作几乎不需要加锁写操作只对涉及的部分加锁。
示例
MapString, Integer concurrentMap new ConcurrentHashMap();
concurrentMap.put(key1, 1); // 线程安全的插入操作
concurrentMap.put(key2, 2);int value concurrentMap.get(key1); // 线程安全的读取操作适用场景ConcurrentHashMap 适合高并发场景尤其在需要频繁读写键值对的情况下性能优于 Collections.synchronizedMap()。 8.3.2 CopyOnWriteArrayList 和 CopyOnWriteArraySet 概述CopyOnWriteArrayList 和 CopyOnWriteArraySet 是基于写时复制Copy-on-Write机制的集合类适用于读多写少的场景。写操作时会将整个数组复制一份进行修改读操作时则不需要加锁。 特点 读操作不会加锁保证高效的读取性能。每次写操作如 add()时会复制整个底层数组所以写操作开销较大适用于写操作较少的场景。
示例
ListString cowList new CopyOnWriteArrayList();
cowList.add(Item 1); // 写操作会复制整个底层数组for (String item : cowList) {System.out.println(item); // 读操作不会加锁
}适用场景适用于读多写少的场景如缓存、配置项加载等。 8.3.3 阻塞队列 (BlockingQueue)
阻塞队列是并发集合框架中的特殊队列支持阻塞的插入和取出操作通常用于生产者-消费者模型。在队列为空时消费者线程会阻塞等待在队列满时生产者线程会阻塞直到有空间为止。
ArrayBlockingQueue 概述ArrayBlockingQueue 是一个基于数组实现的有界阻塞队列队列的大小是固定的。当队列满时生产者线程会阻塞直到有空间插入元素当队列为空时消费者线程会阻塞直到有新的元素入队。
示例
BlockingQueueString arrayBlockingQueue new ArrayBlockingQueue(10);arrayBlockingQueue.put(Item 1); // 阻塞插入当队列满时会等待
String item arrayBlockingQueue.take(); // 阻塞获取当队列为空时会等待适用场景ArrayBlockingQueue 适合在生产者-消费者模型中使用尤其是在对队列长度有明确限制时。
LinkedBlockingQueue 概述LinkedBlockingQueue 是基于链表实现的阻塞队列可以是有界队列设置最大容量也可以是无界队列默认。与 ArrayBlockingQueue 不同LinkedBlockingQueue 的吞吐量通常会更高因为它的生产者和消费者使用独立的锁机制。
示例
BlockingQueueString linkedBlockingQueue new LinkedBlockingQueue();linkedBlockingQueue.put(Item 1); // 阻塞插入
String item linkedBlockingQueue.take(); // 阻塞获取适用场景LinkedBlockingQueue 适合在生产者-消费者模型中使用尤其是对队列长度没有严格限制的情况下。 8.4 总结
同步集合如 Collections.synchronizedList()通过全局锁保证线程安全但性能较低适合并发访问不频繁的场景。并发集合框架如 ConcurrentHashMap、CopyOnWriteArrayList通过更加精细的锁机制或无锁设计适合高并发场景特别是在读多写少、键值对存储、生产者-消费者模型中表现优异。阻塞队列如 ArrayBlockingQueue 和 LinkedBlockingQueue为生产者-消费者模型提供了线程安全的队列操作适用于多线程环境下的任务调度与数据交换。
9. 表格总结
Java 集合框架实现类及其特点与使用情况
集合接口实现类特点使用情况ListArrayList基于动态数组提供 O(1) 的随机访问扩容时会重新分配内存增删元素较慢O(n)。适用于读多写少、需要随机访问元素的场景例如缓存、列表数据存储。LinkedList基于双向链表插入和删除操作高效O(1)但随机访问较慢O(n)。适用于频繁插入和删除操作的场景特别是需要在中间或两端操作的场景例如队列、双端队列。Vector线程安全的 ArrayList但性能较差。适用于早期的 Java 代码中需要线程安全的场景但不推荐在现代开发中使用。CopyOnWriteArrayList基于写时复制写操作时复制整个数组读操作不需要加锁适合读多写少的场景。适用于读多写少的场景例如配置信息的缓存、事件监听器等。SetHashSet基于哈希表提供 O(1) 的插入、删除、查找操作无序。适用于需要保证元素唯一性且不关心顺序的场景例如集合去重。LinkedHashSet基于哈希表和链表按插入顺序存储元素。适用于既需要保证唯一性又需要按照插入顺序遍历元素的场景。TreeSet基于红黑树按自然顺序或自定义 Comparator 进行排序插入、删除、查找时间复杂度 O(log n)。适用于需要保证元素唯一性且按顺序存储的场景例如排序后的集合存储。CopyOnWriteArraySet基于写时复制写操作时复制整个底层数组读操作不加锁适合读多写少的场景。适用于读多写少且需要线程安全的场景例如缓存、线程间共享数据。MapHashMap基于哈希表提供 O(1) 的插入、删除和查找操作键值无序允许 null 键和 null 值。适用于需要快速查找和插入键值对的场景例如存储配置、数据缓存等。LinkedHashMap基于哈希表和链表按插入顺序或访问顺序存储键值对。适用于既需要快速查找又需要保持插入或访问顺序的场景例如缓存实现。TreeMap基于红黑树按键的自然顺序或自定义顺序排序插入、删除、查找时间复杂度 O(log n)。适用于需要按键排序存储键值对的场景例如排序索引、自然顺序存储。ConcurrentHashMap线程安全基于分段锁机制允许多个线程同时访问不同的段读操作无锁写操作只对部分加锁。适用于高并发场景例如计数器、线程安全的缓存。Hashtable线程安全早期版本的 HashMap不允许 null 键和 null 值性能较差。适用于需要线程安全但性能要求较低的场景不推荐使用。QueueLinkedList实现了 Queue 和 Deque 接口支持队列FIFO和双端队列操作。适用于需要双端队列和栈操作的场景例如任务调度、双端队列实现。PriorityQueue基于优先级堆元素按优先级排序默认最小堆不允许 null 元素。适用于需要按优先级处理任务或事件的场景例如事件队列、任务调度。ArrayDeque基于数组的双端队列提供高效的栈和队列操作性能优于 LinkedList。适用于需要双端队列操作且需要高效性能的场景例如栈、队列实现。BlockingQueueArrayBlockingQueue基于数组的有界阻塞队列线程安全队列满时会阻塞插入队列空时会阻塞获取。适用于生产者-消费者模型队列大小固定的场景。LinkedBlockingQueue基于链表的阻塞队列可以是有界或无界队列支持阻塞插入和获取操作。适用于生产者-消费者模型队列大小不固定或较大时的场景。PriorityBlockingQueue基于优先级堆的阻塞队列按优先级排序支持阻塞插入和获取操作。适用于需要按优先级排序的任务调度场景。DequeLinkedList实现了 Deque 接口支持双端队列和栈操作。适用于需要双端队列和栈操作的场景例如任务调度、队列的实现。ArrayDeque基于数组实现的双端队列提供高效的栈和队列操作。适用于需要双端队列操作且需要高效性能的场景性能优于 LinkedList。