前言:
在SpringBoot项目中我们经常会用到集合或数组来存储一些想要的数据列表,或使用Map来方便存取一些键值对,并且Java对集合中提供了很多现有的方法和工具类,一些stream流操作,使用非常方便,本次就给大家介绍一下,常用的Java集合类和使用方法
Java集合框架主要包括两大类:Collection和Map
一、 Collection
有以下几种
1、List
List 是一个接口,继承自 Collection 接口。List 接口表示一个有序的集合,可以包含重复的元素,并且能够精确地控制每个元素的插入位置。用户可以通过索引(从0开始)来访问 List 中的元素。
分为以下:
ArrayList
ArrayList 是 Java 中 List 接口的一个实现类,基于动态数组的数据结构。它允许对元素进行随机访问,并且可以在列表的末尾快速添加和删除元素。然而,在列表中间插入或删除元素可能较慢,因为这需要将后续元素向后或向前移动。
主要特性:
动态数组:
ArrayList 内部使用一个数组来存储元素,并且在需要时可以自动扩容。
非线程安全:
与 Vector 不同,ArrayList 不是线程安全的,因此在多线程环境下需要额外的同步措施。
随机访问:
由于基于数组实现,ArrayList 提供了快速的随机访问能力,通过索引访问元素的时间复杂度为 O(1)。
允许 null 元素:
ArrayList 可以包含一个或多个 null 值。
常用方法:
add(E e): 将指定的元素追加到此列表的末尾。
get(int index): 返回列表中指定位置上的元素。
set(int index, E element): 用指定的元素替代此列表中指定位置上的元素。
remove(int index): 移除此列表中指定位置上的元素。
size(): 返回此列表中的元素数。
contains(Object o): 返回此列表是否包含指定的元素。
clear(): 移除此列表中的所有元素。
toArray(): 将列表转换为数组。
示例代码:
// 创建一个 ArrayList 实例
List<String> arrayList = new ArrayList<>();
// 添加元素
arrayList.add("apple");
arrayList.add("banana");
arrayList.add("orange");
System.out.println("ArrayList content: " + arrayList);
// 访问 ArrayList 中的元素
String firstElement = arrayList.get(0);
System.out.println("First element: " + firstElement);
// 修改 ArrayList 中的元素
arrayList.set(1, "grape");
System.out.println("After modification: " + arrayList);
// 删除 ArrayList 中的元素
arrayList.remove(2);
System.out.println("After removing orange: " + arrayList);
// 获取 ArrayList 的大小
int size = arrayList.size();
System.out.println("Size of ArrayList: " + size);
// 检查 ArrayList 是否包含某个元素
boolean containsApple = arrayList.contains("apple");
System.out.println("Contains 'apple': " + containsApple);
// 清空 ArrayList
arrayList.clear();
System.out.println("After clearing: " + arrayList);
LinkedList
LinkedList 是 Java 中 List 接口的一个实现类,同时也是 Deque(双端队列)接口的实现。它基于双向链表的数据结构,适合频繁地进行插入和删除操作,但在随机访问元素时性能较差。
主要特性:
双向链表:
LinkedList 内部使用一个双向链表来存储元素,每个节点都包含对前一个节点和后一个节点的引用。
线程不安全:
与 Vector 不同,LinkedList 不是线程安全的,因此在多线程环境下需要额外的同步措施。
快速插入和删除:
由于其基于链表的特性,在列表中间插入或删除元素非常高效,时间复杂度为 O(1)。
较慢的随机访问:
通过索引访问元素的时间复杂度为 O(n),因为需要从头或尾遍历到指定位置。
允许 null 元素:
LinkedList 可以包含一个或多个 null 值。
常用方法:
add(E e): 将指定的元素追加到此列表的末尾。
get(int index): 返回列表中指定位置上的元素。
set(int index, E element): 用指定的元素替代此列表中指定位置上的元素。
remove(int index): 移除此列表中指定位置上的元素。
size(): 返回此列表中的元素数。
contains(Object o): 返回此列表是否包含指定的元素。
clear(): 移除此列表中的所有元素。
addFirst(E e): 将指定的元素插入到此列表的开头。
addLast(E e): 将指定的元素添加到此列表的末尾。
removeFirst(): 移除并返回此列表的第一个元素。
removeLast(): 移除并返回此列表的最后一个元素。
示例代码:
// 创建一个 LinkedList 实例
List<String> linkedList = new LinkedList<>();
// 添加元素
linkedList.add("apple");
linkedList.add("banana");
linkedList.add("orange");
System.out.println("LinkedList content: " + linkedList);
// 访问 LinkedList 中的元素
String firstElement = (String) ((LinkedList<?>) linkedList).getFirst();
System.out.println("First element: " + firstElement);
// 修改 LinkedList 中的元素
linkedList.set(1, "grape");
System.out.println("After modification: " + linkedList);
// 删除 LinkedList 中的元素
linkedList.remove(2);
System.out.println("After removing orange: " + linkedList);
// 获取 LinkedList 的大小
int size = linkedList.size();
System.out.println("Size of LinkedList: " + size);
// 检查 LinkedList 是否包含某个元素
boolean containsApple = linkedList.contains("apple");
System.out.println("Contains 'apple': " + containsApple);
// 清空 LinkedList
linkedList.clear();
System.out.println("After clearing: " + linkedList);
// 使用 Deque 特性
LinkedList<String> deque = new LinkedList<>();
deque.addFirst("first");
deque.addLast("last");
System.out.println("Deque content: " + deque);
String removedFirst = deque.removeFirst();
System.out.println("Removed first element: " + removedFirst);
String removedLast = deque.removeLast();
System.out.println("Removed last element: " + removedLast);
Vector
Vector 是 Java 中 List 接口的一个实现类,类似于 ArrayList,但与 ArrayList 不同的是,Vector 是线程安全的。它内部使用动态数组来存储元素,并且在每次扩容时默认将容量增加一倍。
主要特性:
线程安全:
Vector 的所有方法都是同步的(synchronized),这意味着它是线程安全的,可以在多线程环境下使用而无需额外的同步措施。
动态数组:
Vector 内部维护了一个动态数组,当添加的元素超过了当前容量时,它会自动扩容。
性能相对较低:
由于所有的方法都是同步的,这使得 Vector 在单线程环境下的性能不如非同步的 ArrayList。
允许 null 元素:
和 ArrayList 一样,Vector 也允许存储 null 值。
常用方法:
add(E e): 将指定的元素追加到此向量的末尾。
get(int index): 返回此向量中指定位置上的元素。
set(int index, E element): 用指定的元素替换此向量中指定位置上的元素。
remove(int index): 移除此向量中指定位置上的元素。
size(): 返回此向量中的元素数量。
contains(Object o): 返回此向量是否包含指定的元素。
clear(): 移除此向量中的所有元素。
capacity(): 返回此向量的当前容量。
ensureCapacity(int minCapacity): 确保此向量的容量至少等于指定值。
示例代码:
// 创建一个 Vector 实例
Vector<String> vector = new Vector<>();
// 添加元素
vector.add("apple");
vector.add("banana");
vector.add("orange");
System.out.println("Vector content: " + vector);
// 访问 Vector 中的元素
String firstElement = vector.get(0);
System.out.println("First element: " + firstElement);
// 修改 Vector 中的元素
vector.set(1, "grape");
System.out.println("After modification: " + vector);
// 删除 Vector 中的元素
vector.remove(2);
System.out.println("After removing orange: " + vector);
// 获取 Vector 的大小
int size = vector.size();
System.out.println("Size of Vector: " + size);
// 检查 Vector 是否包含某个元素
boolean containsApple = vector.contains("apple");
System.out.println("Contains 'apple': " + containsApple);
// 清空 Vector
vector.clear();
System.out.println("After clearing: " + vector);
// 扩容演示
vector.ensureCapacity(10);
System.out.println("Current capacity after ensuring: " + vector.capacity());
2、Set
Set 是一个不包含重复元素的集合接口。它继承自 Collection 接口
分为以下:
HashSet
HashSet 是 Java 集合框架中 Set 接口的一个实现类。它基于哈希表(Hash Table)实现,不允许集合中存在重复元素,并且不保证元素的存储顺序。
主要特性:
无序性:
HashSet 不维护元素的插入顺序。
唯一性:
HashSet 中的元素是唯一的,不会存储重复值。
线程不安全:
HashSet 是非线程安全的,在多线程环境下可能会出现问题。
常用方法:
add(E e) 向集合中添加指定元素,如果集合已包含该元素,则返回 false。
remove(Object o) 移除指定元素。
contains(Object o) 检查集合是否包含指定元素。
size() 返回集合中的元素数量。
isEmpty() 判断集合是否为空。
clear() 清空集合中的所有元素。
示例代码:
// 创建一个 HashSet 实例
Set<String> set = new HashSet<>();
// 添加元素
set.add("Java");
set.add("Python");
set.add("C++");
set.add("Java"); // 重复元素不会被添加
System.out.println("HashSet content: " + set); // 输出集合内容
// 获取元素个数
int size = set.size();
System.out.println("Size of HashSet: " + size);
// 判断是否包含某个元素
boolean containsPython = set.contains("Python");
System.out.println("Contains Python: " + containsPython);
// 删除指定元素
set.remove("C++");
System.out.println("After removing C++: " + set);
// 清空集合
set.clear();
System.out.println("After clearing: " + set);
LinkedHashSet
LinkedHashSet 是 Java 集合框架中 Set 接口的一个实现类。它是 HashSet 的子类,基于哈希表和链表的组合结构实现。
主要特性:
有序性:
LinkedHashSet 会按照元素的插入顺序存储和返回元素。
唯一性:
和 HashSet 一样,LinkedHashSet 中的元素也是唯一的,不会存储重复值。
线程不安全:
LinkedHashSet 是非线程安全的,在多线程环境下可能会出现问题。
常用方法:
add(E e) 向集合中添加指定元素,如果集合已包含该元素,则返回 false。
remove(Object o) 移除指定元素。
contains(Object o) 检查集合是否包含指定元素。
size() 返回集合中的元素数量。
isEmpty() 判断集合是否为空。
clear() 清空集合中的所有元素。
示例代码:
// 创建一个 LinkedHashSet 实例
Set<String> linkedSet = new LinkedHashSet<>();
// 添加元素
linkedSet.add("Java");
linkedSet.add("Python");
linkedSet.add("C++");
linkedSet.add("Java"); // 重复元素不会被添加
System.out.println("LinkedHashSet content: " + linkedSet); // 输出集合内容
// 获取元素个数
int size = linkedSet.size();
System.out.println("Size of LinkedHashSet: " + size);
// 判断是否包含某个元素
boolean containsPython = linkedSet.contains("Python");
System.out.println("Contains Python: " + containsPython);
// 删除指定元素
linkedSet.remove("C++");
System.out.println("After removing C++: " + linkedSet);
// 清空集合
linkedSet.clear();
System.out.println("After clearing: " + linkedSet);
TreeSet
TreeSet 是 Java 集合框架中 Set 接口的一个实现类。它是基于红黑树(Red-Black Tree)实现的一种有序集合。
主要特性:
元素有序性:
默认情况下,TreeSet 中的元素会按照自然顺序(升序)排列。
唯一性:
和其他 Set 实现一样,TreeSet 不允许存储重复元素。
线程不安全:
TreeSet 是非线程安全的,在多线程环境下可能会出现问题。
常用方法:
add(E e) 向集合中添加指定元素,如果集合已包含该元素,则返回 false。
remove(Object o) 移除指定元素。
contains(Object o) 检查集合是否包含指定元素。
size() 返回集合中的元素数量。
isEmpty() 判断集合是否为空。
clear() 清空集合中的所有元素。
first() 返回集合中的第一个元素(最小值)。
last() 返回集合中的最后一个元素(最大值)。
headSet(E toElement) 返回小于指定元素的子集。
tailSet(E fromElement) 返回大于等于指定元素的子集。
subSet(E fromElement, E toElement) 返回介于两个指定元素之间的子集。
示例代码:
// 创建一个 TreeSet 实例,默认按自然顺序排序
TreeSet<Integer> treeSet = new TreeSet<>();
// 添加元素
treeSet.add(5);
treeSet.add(1);
treeSet.add(3);
treeSet.add(7);
treeSet.add(5); // 重复元素不会被添加
System.out.println("TreeSet content: " + treeSet); // 输出集合内容
// 获取元素个数
int size = treeSet.size();
System.out.println("Size of TreeSet: " + size);
// 获取第一个和最后一个元素
int firstElement = treeSet.first();
int lastElement = treeSet.last();
System.out.println("First Element: " + firstElement);
System.out.println("Last Element: " + lastElement);
// 获取小于指定值的子集
TreeSet<Integer> headSet = (TreeSet<Integer>) treeSet.headSet(5);
System.out.println("Head Set (<5): " + headSet);
// 获取大于等于指定值的子集
TreeSet<Integer> tailSet = (TreeSet<Integer>) treeSet.tailSet(5);
System.out.println("Tail Set (>=5): " + tailSet);
// 清空集合
treeSet.clear();
System.out.println("After clearing: " + treeSet);
二、 Map
Map 是 Java 集合框架中的一个接口,表示键值对(Key-Value)的集合。它主要用于存储具有映射关系的数据,其中每个键(Key)都对应一个值(Value)。Map 中的键是唯一的,而值可以重复。
有以下几种
HashMap
HashMap 是 Java 集合框架中 Map 接口的一个实现类。它基于哈希表(Hash Table)存储数据,并提供键值对(Key-Value)的映射关系。HashMap 允许一个 null 键和多个 null 值,但键必须是唯一的。
主要特性:
基于哈希表:
内部通过哈希算法计算键的哈希值,并根据哈希值确定键值对的存储位置。
无序性:
HashMap 不保证元素的迭代顺序。插入顺序和访问顺序可能不同。
允许一个 null 键和多个 null 值:
一个 HashMap 中只能有一个 null 键(因为键是唯一的),但可以有多个 null 值。
非线程安全:
多线程环境下可能会导致数据不一致,需要手动处理线程安全性。
常用方法:
put(K key, V value) 将键值对存入 HashMap,如果键已存在则替换值。
get(Object key) 根据键获取对应的值。
remove(Object key) 根据键删除键值对。
containsKey(Object key) 判断是否包含指定的键。
containsValue(Object value) 判断是否包含指定的值。
keySet() 返回所有键的集合(Set<K>)。
values() 返回所有值的集合(Collection<V>)。
entrySet() 返回所有键值对的集合(Set<Map.Entry<K,V>>)。
示例代码:
// 创建一个 HashMap 实例
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 28);
// 获取值
System.out.println("张三的年龄:" + map.get("张三"));
// 遍历键值对
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("姓名:" + entry.getKey() + ", 年龄:" + entry.getValue());
}
// 删除键值对
map.remove("李四");
// 判断是否包含某个键
if (map.containsKey("王五")) {
System.out.println("王五存在!");
}
LinkedHashMap
LinkedHashMap 是 HashMap 的子类,继承了 HashMap 的所有特性,并在此基础上增加了对键值对访问顺序或插入顺序的维护能力。它通过维护一个双向链表来记录元素的插入顺序(默认)或访问顺序。
主要特性:
有序性:
默认情况下,LinkedHashMap 按照插入顺序(Insertion Order)保存键值对。
基于哈希表和双向链表:
内部使用哈希表存储数据,同时通过双向链表维护元素的顺序。
允许一个 null 键和多个 null 值:
和 HashMap 一样,LinkedHashMap 允许一个 null 键和多个 null 值。
非线程安全:
和 HashMap 一样,LinkedHashMap 也是非线程安全的。
常用方法:
put(K key, V value) 将键值对存入 LinkedHashMap。
get(Object key) 根据键获取对应的值。
remove(Object key) 根据键删除键值对。
containsKey(Object key) 判断是否包含指定的键。
containsValue(Object value) 判断是否包含指定的值。
keySet() 返回所有键的集合(Set<K>)。
values() 返回所有值的集合(Collection<V>)。
entrySet() 返回所有键值对的集合(Set<Map.Entry<K,V>>)。
示例代码:
// 创建一个 LinkedHashMap 实例,默认按插入顺序
Map<String, Integer> map = new LinkedHashMap<>();
// 添加键值对
map.put("张三", 25);
map.put("李四", 30);
map.put("王五", 28);
// 遍历键值对,输出顺序与插入顺序一致
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("姓名:" + entry.getKey() + ", 年龄:" + entry.getValue());
}
TreeMap
TreeMap 是 Java 集合框架中的一个类,继承自 AbstractMap,并实现了 NavigableMap 接口。它是一种基于红黑树(Red-Black Tree)的数据结构,能够自动对键进行排序。
主要特性:
自动排序:
TreeMap 会对键进行排序,默认情况下是按键的自然顺序排序。
线程不安全:
TreeMap 不是线程安全的,如果在多线程环境中使用,需要手动进行同步。
不允许 null 键:
TreeMap 只允许有一个 null 键(如果使用自然顺序),否则会抛出 NullPointerException。
常用方法:
put(K key, V value) 将指定的键值对插入到 TreeMap 中。
get(Object key) 返回指定键对应的值。
remove(Object key) 删除指定键的键值对。
keySet() 返回 TreeMap 中所有键的集合。
entrySet() 返回 TreeMap 中所有键值对的集合。
firstKey() 返回 TreeMap 中的第一个键(最小键)。
lastKey() 返回 TreeMap 中的最后一个键(最大键)。
ceilingKey(K key) 返回大于或等于给定键的最小键。
floorKey(K key) 返回小于或等于给定键的最大键。
higherKey(K key) 返回大于给定键的最小键。
lowerKey(K key) 返回小于给定键的最大键。
示例代码:
// 创建一个 TreeMap
TreeMap<String, Integer> treeMap = new TreeMap<>();
// 添加键值对
treeMap.put("Tom", 25);
treeMap.put("Jerry", 20);
treeMap.put("Alice", 30);
// 输出 TreeMap 内容
System.out.println("TreeMap 内容:" + treeMap);
// 获取第一个键和最后一个键
System.out.println("第一个键:" + treeMap.firstKey());
System.out.println("最后一个键:" + treeMap.lastKey());
Hashtable
Hashtable 是 Java 集合框架中的一个类,继承自 Dictionary 类,并实现了 Map 接口。它是一个基于哈希表的数据结构,类似于 HashMap,但有一些重要的区别。
主要特性:
线程安全:
Hashtable 是线程安全的,所有的方法都被同步(synchronized),因此可以在多线程环境中安全使用。
不允许 null 键或值:
Hashtable 不允许键或值为 null,否则会抛出 NullPointerException。
常用方法:
put(K key, V value) 将指定的键值对插入到 Hashtable 中。
get(Object key) 返回指定键对应的值。
remove(Object key) 删除指定键的键值对。
containsKey(Object key) 判断是否包含指定的键。
containsValue(Object value) 判断是否包含指定的值。
keySet() 返回 Hashtable 中所有键的集合。
entrySet() 返回 Hashtable 中所有键值对的集合。
size() 返回 Hashtable 中键值对的数量。
isEmpty() 判断 Hashtable 是否为空。
clear() 清空 Hashtable 中的所有键值对。
示例代码:
// 创建一个 Hashtable
Hashtable<String, Integer> hashtable = new Hashtable<>();
// 添加键值对
hashtable.put("Tom", 25);
hashtable.put("Jerry", 20);
hashtable.put("Alice", 30);
// 输出 Hashtable 内容
System.out.println("Hashtable 内容:" + hashtable);
// 获取指定键的值
System.out.println("Tom 的年龄:" + hashtable.get("Tom"));
// 删除指定键的键值对
hashtable.remove("Jerry");
System.out.println("删除 Jerry 后的 Hashtable:" + hashtable);
ConcurrentHashMap
ConcurrentHashMap 是 Java 集合框架中的一个类,也是基于哈希表的数据结构,类似于 HashMap 和 Hashtable。但它通过更细粒度的锁机制(分段锁)实现了更高的并发性能。
主要特性:
线程安全:
ConcurrentHashMap 是线程安全的,但与 Hashtable 不同的是,它并不是对整个表加锁,而是采用了分段锁(Segment Lock)机制,允许多个线程同时访问不同的段,从而提高了并发性能。
高性能:
在 JDK 1.8 中,ConcurrentHashMap 进一步优化了性能,摒弃了分段锁的设计,改用 CAS(Compare-And-Swap)操作和锁条(Lock Striping),使得写操作更加高效。
不允许 null 键或值:
和 HashMap 类似,ConcurrentHashMap 不允许存储 null 键或 null 值。如果尝试插入 null 键或值,会抛出NullPointerException。
常用方法:
put(K key, V value) 插入键值对
get(Object key) 根据键获取值
remove(Object key) 根据键删除键值对
size() 返回键值对的数量
isEmpty() 判断是否为空
containsKey(Object key) 判断是否包含指定的键
containsValue(Object value) 判断是否包含指定的值
clear() 清空所有键值对
示例代码:
// 创建一个 ConcurrentHashMap
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
// 插入键值对
map.put("Java", 1);
map.put("Python", 2);
map.put("C++", 3);
// 获取值
System.out.println("Java: " + map.get("Java")); // 输出:Java: 1
// 删除键值对
map.remove("Python");
// 遍历键值对
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
// 输出:Java: 1
// C++: 3
本次教程到这里就结束了,希望大家多多关注支持(首席摸鱼师 微信同号),持续跟踪最新文章吧~