Java集合
一、什么是Java集合?
Java集合(Java Collections)是Java中用于存储、操作和管理一组对象的数据结构框架。它提供了一套接口和类,帮助开发者以统一的方式处理各种类型的集合,如列表、集合、队列和映射。Java集合框架使得开发者可以轻松地处理数据结构,不需要自己实现复杂的数据结构算法。
主要组成部分:
-
核心接口:
- Collection:这是最基本的集合接口,它提供了一些通用的集合操作方法,如添加、删除、遍历等。
List
、Set
和Queue
接口都继承自Collection
。- List:有序集合,允许重复元素。例如:
ArrayList
、LinkedList
。 - Set:无序集合,不允许重复元素。例如:
HashSet
、TreeSet
。 - Queue:队列,遵循FIFO(先进先出)原则,例如:
PriorityQueue
。 - Deque:双端队列,支持在两端插入和删除元素,例如:
ArrayDeque
。
- List:有序集合,允许重复元素。例如:
- Collection:这是最基本的集合接口,它提供了一些通用的集合操作方法,如添加、删除、遍历等。
-
Map接口:
- Map:并不继承
Collection
,但也是Java集合框架的一部分。它存储键值对,每个键都唯一。例如:HashMap
、TreeMap
、LinkedHashMap
。
- Map:并不继承
-
重要实现类:
- ArrayList:基于动态数组的
List
实现,查找元素速度快,增删效率相对较慢。 - LinkedList:基于链表的
List
实现,增删速度快,查找效率较低。 - HashSet:基于哈希表实现的
Set
,不保证元素顺序。 - TreeSet:基于红黑树实现的
Set
,元素是有序的。 - HashMap:基于哈希表实现的
Map
,允许null
键和null
值。 - TreeMap:基于红黑树实现的
Map
,键按自然顺序或自定义比较器排序。
- ArrayList:基于动态数组的
-
Collections工具类:
- 提供了对集合操作的实用方法,例如排序、查找、同步化集合等功能。
Java集合框架通过使用泛型,提供了类型安全的集合操作,从而避免了在运行时发生类型转换错误。
你可以根据需要选择不同的集合类型来存储和操作数据。
二、Collections工具类
Java中的Collections
工具类是一个包含多个静态方法的实用类,提供了对集合进行各种操作的工具。通过Collections
类,你可以执行排序、查找、同步化、打乱顺序等操作。以下是Collections
工具类的一些常用方法:
1. 排序相关方法:
sort(List<T> list)
:对List
集合中的元素进行升序排序,要求集合中的元素实现Comparable
接口。sort(List<T> list, Comparator<? super T> c)
:使用指定的Comparator
对List
集合中的元素进行排序。reverse(List<?> list)
:将List
中的元素顺序反转。
2. 查找和替换相关方法:
binarySearch(List<? extends Comparable<? super T>> list, T key)
:使用二分查找算法在有序List
中查找元素,返回元素的索引。binarySearch(List<? extends T> list, T key, Comparator<? super T> c)
:使用二分查找算法和自定义比较器查找元素。max(Collection<? extends T> coll)
:返回集合中的最大元素,要求集合中的元素实现Comparable
接口。max(Collection<? extends T> coll, Comparator<? super T> comp)
:使用指定的Comparator
,返回集合中的最大元素。min(Collection<? extends T> coll)
:返回集合中的最小元素。min(Collection<? extends T> coll, Comparator<? super T> comp)
:使用指定的Comparator
,返回集合中的最小元素。replaceAll(List<T> list, T oldVal, T newVal)
:将List
中的所有oldVal
替换为newVal
。
3. 同步和不可变集合相关方法:
synchronizedList(List<T> list)
:返回一个线程安全的List
。synchronizedSet(Set<T> s)
:返回一个线程安全的Set
。synchronizedMap(Map<K, V> m)
:返回一个线程安全的Map
。unmodifiableList(List<? extends T> list)
:返回一个不可修改的List
。unmodifiableSet(Set<? extends T> set)
:返回一个不可修改的Set
。unmodifiableMap(Map<? extends K, ? extends V> m)
:返回一个不可修改的Map
。
4. 打乱顺序相关方法:
shuffle(List<?> list)
:随机打乱List
集合中的元素顺序。shuffle(List<?> list, Random rnd)
:使用指定的随机数生成器打乱List
中的元素顺序。
5. 集合频率与填充相关方法:
frequency(Collection<?> c, Object o)
:返回指定元素在集合中出现的次数。fill(List<? super T> list, T obj)
:将List
中的所有元素都替换为指定的元素。copy(List<? super T> dest, List<? extends T> src)
:将src
中的所有元素复制到dest
中,要求dest
至少与src
的大小相等。
6. 集合比较相关方法:
disjoint(Collection<?> c1, Collection<?> c2)
:如果两个集合没有交集,则返回true
。nCopies(int n, T o)
:返回包含n
个o
元素的不可修改列表。
7. 集合旋转相关方法:
rotate(List<?> list, int distance)
:将List
中的元素按照指定距离旋转(正值右移,负值左移)。
8. 集合交换相关方法:
swap(List<?> list, int i, int j)
:交换List
中索引i
和索引j
处的元素。
9. 集合填充相关方法:
addAll(Collection<? super T> c, T... elements)
:向集合中添加多个元素。singleton(T o)
:返回一个只包含单一对象的不可修改Set
。singletonList(T o)
:返回一个只包含单一对象的不可修改List
。singletonMap(K key, V value)
:返回一个只包含单一键值对的不可修改Map
。
10. 空集合相关方法:
emptyList()
:返回一个空的不可修改List
。emptySet()
:返回一个空的不可修改Set
。emptyMap()
:返回一个空的不可修改Map
。
这些方法为开发者提供了丰富的集合操作手段,能够简化集合的处理工作,同时确保代码的简洁性和可读性。
三、集合类中线程安全的实现
在 Java 集合框架中,实现线程安全的集合类有多种方式。下面是几种常见的线程安全实现:
1. Vector
和 Hashtable
- 早期的集合类如
Vector
和Hashtable
本身是线程安全的,因为它们的方法都使用了synchronized
关键字。 - 这些类的缺点是性能较低,因为每个方法调用都会加锁,即使在没有竞争的情况下也会导致性能开销。
2. Collections.synchronizedXXX()
方法
-
通过
Collections.synchronizedXXX()
方法,可以将非线程安全的集合(如ArrayList
、HashMap
等)转换为线程安全的版本。 -
例如:
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>()); Map<String, String> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
-
这种方法会对整个集合的访问加锁,但需要注意的是,遍历集合时仍然需要手动同步:
synchronized(synchronizedList) { for (String item : synchronizedList) { // Do something with item } }
-
这种实现方法的优点是可以让你灵活地使用各种集合类,但由于它对每个方法调用加锁,性能可能较低。
3. ConcurrentHashMap
-
ConcurrentHashMap
是HashMap
的线程安全版本,它使用了一种更高效的并发控制机制,允许多线程在不同的分段(segment)上并发读写,而不需要锁整个集合。 -
相比
Collections.synchronizedMap
,ConcurrentHashMap
在并发性能上有显著提升,尤其是读多写少的场景。 -
例如:
Map<String, String> concurrentMap = new ConcurrentHashMap<>();
-
ConcurrentHashMap
还引入了一些额外的并发操作方法,如putIfAbsent()
、computeIfAbsent()
等。
4. CopyOnWriteArrayList
和 CopyOnWriteArraySet
-
CopyOnWriteArrayList
和CopyOnWriteArraySet
是基于写时复制(Copy-On-Write)的集合类,适用于读操作远多于写操作的场景。 -
每次写操作都会复制底层数组,写操作性能较低,但读操作不需要加锁,性能非常高。
-
例如:
List<String> cowList = new CopyOnWriteArrayList<>(); Set<String> cowSet = new CopyOnWriteArraySet<>();
5. BlockingQueue
(如 LinkedBlockingQueue
、ArrayBlockingQueue
)
BlockingQueue
是线程安全的队列实现,适用于生产者-消费者模型。它提供了阻塞的put()
和take()
方法,用于线程之间安全地共享数据。- 常见的实现包括
LinkedBlockingQueue
、ArrayBlockingQueue
等。
6. ConcurrentSkipListMap
和 ConcurrentSkipListSet
-
这两个类是线程安全的、基于跳表的数据结构,它们是有序集合,可以用在需要线程安全且有序的场景中。
-
例如:
Map<String, String> skipListMap = new ConcurrentSkipListMap<>(); Set<String> skipListSet = new ConcurrentSkipListSet<>();
总结:
- 如果是读多写少的场景,可以考虑
CopyOnWriteArrayList
。 - 如果需要高效的并发访问并且不需要严格的同步控制,
ConcurrentHashMap
是一个很好的选择。 - 如果需要简单的线程安全集合,可以使用
Collections.synchronizedXXX()
。 - 对于队列模型,
BlockingQueue
是非常合适的选择。
四、Java集合类实战
Java 集合类是 Java 编程中的基础工具之一,用于存储和操作一组对象。集合类提供了多种不同的数据结构和算法,包括列表、集合、映射等。下面将通过几个常见的集合类的实际应用场景,介绍它们的使用。
1. ArrayList 实战:动态数组
场景:需要存储一个可变长度的元素列表,并且对顺序进行严格的管理。
示例代码:
import java.util.ArrayList;
import java.util.List;
public class ArrayListExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Orange");
// 遍历列表
for (String fruit : list) {
System.out.println(fruit);
}
// 获取元素
String firstFruit = list.get(0);
System.out.println("First Fruit: " + firstFruit);
// 删除元素
list.remove("Banana");
System.out.println("After removal: " + list);
}
}
适用场景:当需要频繁读取元素且元素顺序重要时,ArrayList
是理想的选择。
2. HashSet 实战:去重和无序集合
场景:需要存储一组不重复的元素,并且不关心元素的顺序。
示例代码:
import java.util.HashSet;
import java.util.Set;
public class HashSetExample {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Orange");
set.add("Apple"); // 重复的元素不会被添加
// 遍历集合
for (String fruit : set) {
System.out.println(fruit);
}
// 判断是否包含某个元素
boolean containsApple = set.contains("Apple");
System.out.println("Contains Apple? " + containsApple);
}
}
适用场景:需要避免重复元素时,HashSet
是最佳选择。
3. HashMap 实战:键值对存储
场景:需要将一组键值对进行存储和快速检索。
示例代码:
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// 添加键值对
map.put("Apple", 10);
map.put("Banana", 20);
map.put("Orange", 30);
// 遍历 Map
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 获取特定键对应的值
int applePrice = map.get("Apple");
System.out.println("Price of Apple: " + applePrice);
// 删除键值对
map.remove("Banana");
System.out.println("After removal: " + map);
}
}
适用场景:需要通过键快速查找数据时,HashMap
是常用选择。
4. LinkedList 实战:双向链表
场景:需要频繁对集合的两端进行操作(如插入和删除)。
示例代码:
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.addFirst("Orange"); // 在头部插入
list.addLast("Grape"); // 在尾部插入
// 遍历列表
for (String fruit : list) {
System.out.println(fruit);
}
// 删除元素
list.removeFirst(); // 删除头部
list.removeLast(); // 删除尾部
System.out.println("After removal: " + list);
}
}
适用场景:当需要频繁在列表头尾操作时,LinkedList
具有更高的性能。
5. TreeSet 实战:有序集合
场景:需要存储一组不重复且有序的元素。
示例代码:
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<>();
// 添加元素
set.add("Banana");
set.add("Apple");
set.add("Orange");
// 遍历集合(自动按字典顺序排序)
for (String fruit : set) {
System.out.println(fruit);
}
// 获取最小和最大元素
System.out.println("First: " + set.first());
System.out.println("Last: " + set.last());
}
}
适用场景:需要存储有序元素时,TreeSet
是理想的选择。
6. PriorityQueue 实战:优先级队列
场景:需要按优先级顺序处理任务或元素。
示例代码:
import java.util.PriorityQueue;
public class PriorityQueueExample {
public static void main(String[] args) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
// 添加元素
queue.add(10);
queue.add(20);
queue.add(5);
// 处理元素(自动按升序排列)
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
适用场景:需要按优先级处理任务时,PriorityQueue
非常适合。
总结
Java 集合类为我们提供了多种处理不同数据需求的工具。在实际开发中,选择合适的集合类不仅可以提高程序性能,还可以让代码更加简洁和可读。
标签:Map,Java,list,元素,List,集合 From: https://blog.csdn.net/golove666/article/details/141993449