Java集合框架是一组接口和类,用于表示和操作集合,允许我们以各种方式存储和操作对象组。Java集合框架主要分为两大类:Collection接口和Map接口 。下面从这两方面介绍,并介绍常用的集合类,如ArrayList,HashSet和HashMap。
目录
[1. 常用的Collection衍生接口或类](#1. 常用的Collection衍生接口或类)
[2. Collection接口常用的方法(通用方法)](#2. Collection接口常用的方法(通用方法))
[3. ArrayList](#3. ArrayList)
[① 构造方法](#① 构造方法)
[② 元素添加](#② 元素添加)
[③ 元素删除](#③ 元素删除)
[④ 元素修改](#④ 元素修改)
[⑤ 元素查询](#⑤ 元素查询)
[⑥ 转换操作](#⑥ 转换操作)
[⑦ 视图和迭代器](#⑦ 视图和迭代器)
[⑧ 大小和容量](#⑧ 大小和容量)
[⑨ 其他](#⑨ 其他)
[4. HashSet](#4. HashSet)
[① 构造函数](#① 构造函数)
[② 增加元素](#② 增加元素)
[③ 删除元素](#③ 删除元素)
[④ 查找元素](#④ 查找元素)
[⑤ 其他方法](#⑤ 其他方法)
[1. 常用的Map衍生类](#1. 常用的Map衍生类)
[2. HashMap](#2. HashMap)
[① 构造函数](#① 构造函数)
[② 增删改查和遍历](#② 增删改查和遍历)
[③ 获取key和value](#③ 获取key和value)
[④ Stream流](#④ Stream流)
[⑤ 其他方法](#⑤ 其他方法)
[1. ArrayList](#1. ArrayList)
[(1)定义一个ArrayList,并添加以下元素:1, 2, 3, 4, 5。然后使用循环遍历并打印所有元素。](#(1)定义一个ArrayList,并添加以下元素:1, 2, 3, 4, 5。然后使用循环遍历并打印所有元素。)
(2)移除索引为2的元素,并输出修改后的ArrayList。
(3)给定一个包含整数的ArrayList,编写一个方法来计算所有元素的和。
(4)给定一个包含字符串的ArrayList,编写一个方法来删除所有包含字母"b"的字符串。
(5)将ArrayList反转,并输出反转后的ArrayList。(使用Collections)
(6)给定一个包含整数的ArrayList,编写一个方法来找出最大的元素。
(7)给定两个包含整数的ArrayList,编写一个方法来合并这两个ArrayList,并去除重复元素,并进行排序。
[(8)给定一个整型ArrayList {10, 20, 30, 40, 50},请找出数字30的索引位置,并输出结果。](#(8)给定一个整型ArrayList {10, 20, 30, 40, 50},请找出数字30的索引位置,并输出结果。)
[(9)给定一个整型ArrayList {1, 2, 3, 4, 5},将其每个元素乘以2,并输出结果。](#(9)给定一个整型ArrayList {1, 2, 3, 4, 5},将其每个元素乘以2,并输出结果。)
[2. HashSet](#2. HashSet)
(12)从HashSet中删除一个元素,并输出删除后的HashSet。
(15)给定两个HashSet,创建一个方法来计算它们的并集。
[3. HashMap](#3. HashMap)
(17)创建一个HashMap,并添加5个键值对,然后遍历并打印所有键值对。
(21)合并两个HashMap,如果键相同,则将对应的值相加。
进阶知识:Stream API
可参考 Stream API 详解和25道练习题-CSDN博客
一、Collection接口
1. 常用的Collection衍生接口或类
(1)List接口
它扩展了Collection接口,用于存储有序集合,允许重复元素。常用实现类有:
- ArrayList: 使用动态数组实现,适合频繁的查找和更新操作。
- LinkedList: 使用双向链表实现,适合频繁的插入和删除操作。
(2)Set接口
它也扩展了Collection接口,用于存储无序集合,不允许重复元素。常用实现类有:
- HashSet: 基于哈希表实现,存储无序集合。
- LinkedHashSet: 保持插入顺序的哈希表实现。
- TreeSet: 基于红黑树实现,元素按照自然顺序或者Comparator排序。
(3)Queue接口
用于存储待处理的元素序列,按照特定的顺序处理它们。常用实现类有:
- PriorityQueue: 一个基于优先级堆的无界优先队列。
- LinkedList: 也可以用作Queue的实现。
(4)Deque接口
双端队列,允许元素从两端被添加或移除。常用实现类有:
- ArrayDeque: 使用循环数组实现。
2. Collection接口常用的方法(通用方法)
(1)添加元素
- boolean add(E e): 确保此集合包含指定的元素(可选操作)。
- boolean addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到此集合中(可选操作)。
(2)删除元素
- boolean remove(Object o): 从此集合中移除指定元素的单个实例,如果存在(可选操作)。
- boolean removeAll(Collection<?> c): 移除此集合中所有也包含在指定集合中的元素(可选操作)。
- default boolean removeIf(Predicate<? super E> filter): 移除满足给定条件的所有元素。
- boolean retainAll(Collection<?> c): 仅保留此集合中包含在指定集合中的元素(可选操作)。
- void clear(): 清除此集合中的所有元素(可选操作)。
(3)检查元素
- boolean contains(Object o): 如果此集合包含指定的元素,则返回 true。
- boolean containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回 true。
- boolean isEmpty(): 如果此集合不包含元素,则返回 true。
(4)获取大小
- int size(): 返回此集合中的元素数。
(5)转换为数组
- Object[] toArray(): 返回包含此集合中所有元素的数组。
- <T> T[] toArray(T[] a): 返回包含此集合中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
(6)迭代器
- Iterator<E> iterator(): 返回此集合中元素的迭代器。
(7)流操作
- default Stream<E> stream(): 返回一个以此集合作为源的顺序流。
- default Stream<E> parallelStream(): 返回可能并行的 Stream 与此集合作为其源。
(8)其他
- boolean equals(Object o): 比较指定对象与此集合是否相等。
- int hashCode(): 返回此集合的哈希码值。
(9)示例代码
java
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
// 创建一个ArrayList集合
Collection<String> collection = new ArrayList<>();
// 添加元素
collection.add("Apple");
collection.add("Banana");
collection.add("Cherry");
System.out.println("添加元素后: " + collection); // 输出: [Apple, Banana, Cherry]
// 添加另一个集合的元素
Collection<String> anotherCollection = new ArrayList<>();
anotherCollection.add("Dragonfruit");
anotherCollection.add("Elderberry");
collection.addAll(anotherCollection);
System.out.println("添加另一个集合后: " + collection); // 输出: [Apple, Banana, Cherry, Dragonfruit, Elderberry]
// 删除元素
collection.remove("Banana");
System.out.println("删除'Banana'后: " + collection); // 输出: [Apple, Cherry, Dragonfruit, Elderberry]
// 移除所有指定集合中的元素
collection.removeAll(anotherCollection);
System.out.println("移除所有另一个集合中的元素后: " + collection); // 输出: [Apple, Cherry]
// 使用removeIf移除满足条件的元素
collection.removeIf(s -> s.startsWith("A"));
System.out.println("移除以'A'开头的元素后: " + collection); // 输出: [Cherry]
// 仅保留指定集合中的元素
collection.addAll(anotherCollection);
collection.retainAll(anotherCollection);
System.out.println("仅保留另一个集合中的元素后: " + collection); // 输出: [Dragonfruit, Elderberry]
// 清空集合
collection.clear();
System.out.println("清空集合后: " + collection); // 输出: []
// 重新添加元素以进行后续操作
collection.add("Apple");
collection.add("Banana");
collection.add("Cherry");
// 检查元素
System.out.println("包含'Banana': " + collection.contains("Banana")); // 输出: true
System.out.println("包含另一个集合的所有元素: " + collection.containsAll(anotherCollection)); // 输出: false
// 检查集合是否为空
System.out.println("集合是否为空: " + collection.isEmpty()); // 输出: false
// 获取集合大小
System.out.println("集合的大小: " + collection.size()); // 输出: 3
// 转换为数组
Object[] array = collection.toArray();
System.out.println("从集合转换的数组: " + java.util.Arrays.toString(array)); // 输出: [Apple, Banana, Cherry]
// 使用指定的数组类型转换
String[] stringArray = collection.toArray(new String[0]);
System.out.println("从集合转换的字符串数组: " + java.util.Arrays.toString(stringArray)); // 输出: [Apple, Banana, Cherry]
// 迭代器
System.out.print("遍历集合: ");
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println(); // 输出: 遍历集合: Apple Banana Cherry
// 流操作
List<String> uppercaseList = collection.stream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println("从集合生成的全大写列表: " + uppercaseList); // 输出: [APPLE, BANANA, CHERRY]
// 并行流操作
List<String> uppercaseParallelList = collection.parallelStream().map(String::toUpperCase).collect(Collectors.toList());
System.out.println("从集合生成的并行全大写列表: " + uppercaseParallelList); // 输出: [APPLE, BANANA, CHERRY]
// 比较集合
Collection<String> sameCollection = new ArrayList<>();
sameCollection.add("Apple");
sameCollection.add("Banana");
sameCollection.add("Cherry");
System.out.println("集合是否与sameCollection相等: " + collection.equals(sameCollection)); // 输出: true
// 获取哈希码
System.out.println("集合的哈希码: " + collection.hashCode()); // 输出: 哈希码值,具体值取决于元素和顺序
}
}
3. ArrayList
ArrayList 是 Java 中的一个非常重要的集合框架类,它实现了 List 接口,并提供了可调整大小的数组实现。
(1)特点
- 动态数组:与传统的数组不同,ArrayList 在运行时可以动态地调整其大小,这提供了极大的灵活性。
- 易于使用:ArrayList 提供了丰富的接口和方法,使得添加、删除、访问和修改列表中的元素变得非常容易。
- 接口丰富:实现了 List 接口,意味着它拥有 List 的所有功能,并且可以很容易地与 Java 集合框架的其他部分交互。
- 性能:对于随机访问元素来说,ArrayList 的效率很高,因为它底层是数组。
(2)常用方法
① 构造方法
- ArrayList(): 创建一个空的 ArrayList。
- ArrayList(Collection<? extends E> c): 创建一个包含指定集合元素的 ArrayList。
- ArrayList(int initialCapacity): 创建一个具有指定初始容量的空 ArrayList。
② 元素添加
- boolean add(E e): 在列表末尾添加元素。
- void add(int index, E element): 在指定位置添加元素。
- boolean addAll(Collection<? extends E> c): 添加指定集合中的所有元素到列表末尾。
- boolean addAll(int index, Collection<? extends E> c): 将指定集合中的所有元素插入到列表中的指定位置。
③ 元素删除
- void clear(): 移除列表中的所有元素。
- boolean remove(Object o): 移除列表中首次出现的指定元素。
- E remove(int index): 移除列表中指定位置的元素。
- boolean removeAll(Collection<?> c): 移除列表中包含在指定集合中的所有元素。
- boolean removeIf(Predicate<? super E> filter): 移除满足给定条件的所有元素。
- protected void removeRange(int fromIndex, int toIndex): 私有方法,用于移除列表中指定范围的元素。
- boolean retainAll(Collection<?> c): 仅保留列表中包含在指定集合中的元素。
④ 元素修改
- E set(int index, E element): 用指定元素替换列表中指定位置的元素。
⑤ 元素查询
- boolean contains(Object o): 如果列表包含指定的元素,则返回 true。
- boolean containsAll(Collection<?> c): 如果列表包含指定集合的所有元素,则返回 true。
- E get(int index): 返回列表中指定位置的元素。
- int indexOf(Object o): 返回列表中首次出现的指定元素的索引,如果不存在则返回 -1。
- int lastIndexOf(Object o): 返回列表中最后一次出现的指定元素的索引,如果不存在则返回 -1。
- boolean isEmpty(): 如果列表不包含元素,则返回 true。
⑥ 转换操作
- Object[] toArray(): 返回一个包含列表所有元素的数组。
- <T> T[] toArray(T[] a): 返回一个包含列表所有元素的数组;返回数组的运行时类型是指定数组的类型。
⑦ 视图和迭代器
- List<E> subList(int fromIndex, int toIndex): 返回列表中指定的 fromIndex(包含)和 toIndex(不包含)之间的部分视图。
- Iterator<E> iterator(): 返回列表中的迭代器。
- ListIterator<E> listIterator(): 返回列表中的列表迭代器。
- ListIterator<E> listIterator(int index): 返回列表中从指定位置开始的列表迭代器。
⑧ 大小和容量
- int size(): 返回列表中的元素数量。
- void ensureCapacity(int minCapacity): 如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数指定的元素数量。
⑨ 其他
- void trimToSize(): 修改这个 ArrayList 实例的容量为列表的当前大小。
- protected void finalize(): 当垃圾回收器确定不再有对对象的引用时,由垃圾回收器调用此方法。
(3)示例代码
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Main {
public static void main(String[] args) {
// 创建一个空的 ArrayList
ArrayList<String> list = new ArrayList<>();
// 添加元素
list.add("Apple"); // list: [Apple]
list.add("Banana"); // list: [Apple, Banana]
list.add(1, "Cherry"); // list: [Apple, Cherry, Banana]
// 添加集合中的所有元素
ArrayList<String> fruitsToBeAdded = new ArrayList<>(Arrays.asList("Date", "Elderberry"));
list.addAll(fruitsToBeAdded); // list: [Apple, Cherry, Banana, Date, Elderberry]
// 输出列表
System.out.println(list); // 实际输出: [Apple, Cherry, Banana, Date, Elderberry]
// 移除元素
list.remove("Banana"); // list: [Apple, Cherry, Date, Elderberry]
list.remove(2); // list: [Apple, Cherry, Elderberry]
// 移除满足条件的所有元素
list.removeIf(s -> s.startsWith("E")); // list: [Apple, Cherry]
// 替换元素
list.set(1, "Grape"); // list: [Apple, Grape]
// 查询元素
boolean containsApple = list.contains("Apple"); // containsApple: true
System.out.println(containsApple); // 实际输出: true
// 获取元素
String firstElement = list.get(0); // firstElement: Apple
System.out.println(firstElement); // 实际输出: Apple
// 查找元素的索引
int indexOfGrape = list.indexOf("Grape"); // indexOfGrape: 1
System.out.println(indexOfGrape); // 实际输出: 1
// 检查列表是否为空
boolean isEmpty = list.isEmpty(); // isEmpty: false
System.out.println(isEmpty); // 实际输出: false
// 转换操作
Object[] array = list.toArray(); // array: [Apple, Grape]
System.out.println(Arrays.toString(array)); // 实际输出: [Apple, Grape]
// 视图和迭代器
List<String> sublist = list.subList(0, 1); // sublist: [Apple]
System.out.println(sublist); // 实际输出: [Apple]
// 迭代器
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next()); // 实际输出: Apple Grape
}
// 列表迭代器
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
System.out.println(listIterator.nextIndex() + ": " + listIterator.next()); // 实际输出: 0: Apple 1: Grape
}
// 大小和容量
int size = list.size(); // size: 2
System.out.println(size); // 实际输出: 2
// 确保容量
list.ensureCapacity(10); // 确保列表至少可以容纳10个元素
// 修改容量为当前大小
list.trimToSize(); // 修改列表的容量为当前元素数量
// 清除所有元素
list.clear(); // list: []
System.out.println(list); // 实际输出: []
}
}
4. HashSet
HashSet 是 Java 集合框架中的一部分,它实现了 Set 接口,背后是由 HashMap 支持的。以下是 HashSet 的一些特点和它提供的主要函数。
(1)特点
- 不包含重复元素:HashSet 中不允许有重复的元素,如果试图添加一个已经在 HashSet 中的元素,则添加操作不会产生任何效果。
- 不保证元素的顺序:HashSet 不保证元素的顺序,也就是说,它不会按照元素的添加顺序保存元素。
- 非线程安全:HashSet 不是线程同步的,如果多个线程同时访问 HashSet,并且至少有一个线程修改了 HashSet,则必须保持外部同步。
- 允许包含 null 值:HashSet 可以包含一个 null 元素。
- 高性能:HashSet 提供了常数时间性能的添加、删除和包含操作,前提是哈希函数能够将元素正确地分散到各个桶中。
(2)常用方法
① 构造函数
- HashSet(): 创建一个默认初始容量为16,加载因子为0.75的空集合。
- HashSet(int initialCapacity): 创建一个指定初始容量的空集合。
- HashSet(int initialCapacity, float loadFactor): 创建一个指定初始容量和加载因子的空集合。
- HashSet(Collection<? extends E> c): 创建一个包含指定集合中的元素的集合。
② 增加元素
- boolean add(E e): 如果集合中没有指定元素,则添加并返回true,否则返回false。
- boolean addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到此集合中,如果集合因此改变,则返回true。
③ 删除元素
- boolean remove(Object o): 如果存在,则从集合中移除指定元素,并返回true。
- boolean removeAll(Collection<?> c): 移除此集合中那些也包含在指定集合中的所有元素,如果此集合因此改变,则返回true。
- boolean retainAll(Collection<?> c): 仅保留此集合中那些也包含在指定集合中的元素,如果此集合因此改变,则返回true。
- void clear(): 从此集合中移除所有元素。
④ 查找元素
- boolean contains(Object o): 如果此集合包含指定的元素,则返回true。
- boolean containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回true。
- boolean isEmpty(): 如果此集合不包含任何元素,则返回true。
- int size(): 返回此集合中的元素数量。
⑤ 其他方法
- boolean removeIf(Predicate<? super E> filter): 移除此集合中满足给定谓词的所有元素。
- void forEach(Consumer<? super E> action): 对此集合中的每个元素执行给定操作。
- Spliterator<E> spliterator(): 在此集合中的元素上创建一个Spliterator。
- Stream<E> stream(): 返回此集合中元素的串行流。
- Stream<E> parallelStream(): 返回此集合中元素的并行流。
- Object clone(): 返回此 HashSet 实例的浅拷贝。
- int hashCode(): 返回此集合的哈希码值。
- boolean equals(Object o): 比较指定对象与此集合是否相等。
(3)示例代码
java
import java.util.Collection;
import java.util.HashSet;
import java.util.Spliterator;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
// 创建一个默认初始容量为16,加载因子为0.75的空集合
HashSet<String> hashSet = new HashSet<>();
// 添加元素
System.out.println(hashSet.add("Apple")); // true
System.out.println(hashSet.add("Banana")); // true
System.out.println(hashSet.add("Apple")); // false,因为已经存在
// 使用指定初始容量的空集合
HashSet<String> hashSetWithCapacity = new HashSet<>(30);
// 使用指定初始容量和加载因子的空集合
HashSet<String> hashSetWithLoadFactor = new HashSet<>(30, 0.5f);
// 创建一个包含指定集合中的元素的集合
Collection<String> collection = new HashSet<>();
collection.add("Cherry");
collection.add("Date");
HashSet<String> hashSetFromCollection = new HashSet<>(collection);
System.out.println(hashSetFromCollection); // [Cherry, Date]
// 将指定集合中的所有元素添加到此集合中
System.out.println(hashSet.addAll(hashSetFromCollection)); // true
// 从集合中移除指定元素
System.out.println(hashSet.remove("Banana")); // true
// 移除此集合中那些也包含在指定集合中的所有元素
System.out.println(hashSet.removeAll(collection)); // true
// 仅保留此集合中那些也包含在指定集合中的元素
hashSet.add("Apple");
hashSet.add("Banana");
System.out.println(hashSet.retainAll(hashSetFromCollection)); // true
// 从此集合中移除所有元素
hashSet.clear();
System.out.println(hashSet.isEmpty()); // true
// 查找元素
hashSet.add("Apple");
System.out.println(hashSet.contains("Apple")); // true
System.out.println(hashSet.containsAll(collection)); // false
// 返回此集合中的元素数量
System.out.println(hashSet.size()); // 1
// Java 8 新增方法
// 移除此集合中满足给定谓词的所有元素
hashSet.add("Banana");
hashSet.removeIf(s -> s.startsWith("B"));
System.out.println(hashSet); // [Apple]
// 对此集合中的每个元素执行给定操作
hashSet.forEach(s -> System.out.println(s)); // Apple
// 在此集合中的元素上创建一个Spliterator
Spliterator<String> spliterator = hashSet.spliterator();
spliterator.forEachRemaining(System.out::println); // Apple
// 返回此集合中元素的串行流
Stream<String> stream = hashSet.stream();
stream.forEach(System.out::println); // Apple
// 返回此集合中元素的并行流
Stream<String> parallelStream = hashSet.parallelStream();
parallelStream.forEach(System.out::println); // Apple
// 返回此 HashSet 实例的浅拷贝
HashSet<String> cloneHashSet = (HashSet<String>) hashSet.clone();
System.out.println(cloneHashSet); // [Apple]
// 返回此集合的哈希码值
System.out.println(hashSet.hashCode());
// 比较指定对象与此集合是否相等
System.out.println(hashSet.equals(cloneHashSet)); // true
}
}
二、Map 接口
1. 常用的Map衍生类
(1)HashMap类
它基于哈希表实现,存储键值对,允许使用null键和null值。它不保证元素的顺序,特别适合在插入和查询操作中快速访问元素。
(2)LinkedHashMap类
继承自HashMap,但它维护了一个运行于所有条目的双重链接列表。这个链接列表定义了迭代顺序,通常是插入顺序,也可以在构造时指定为访问顺序。
(3)TreeMap类
基于红黑树实现,可以确保键值对按照键的自然顺序或者Comparator排序。它提供了操作键值对的各种方法,如获取第一个键、最后一个键等。
(4)Hashtable类
它是遗留类,与HashMap类似,但它不允许使用null键或null值,并且所有的方法都是同步的,即线程安全的。
(5)ConcurrentHashMap类
是一个线程安全的哈希表,用于替代Hashtable。它支持高并发性,通过分段锁技术,允许多个线程并发访问Map的不同部分。
2. HashMap
(1)特点
- 键值对存储:HashMap基于键值对(Key-Value Pair)存储数据,每个键对应一个值,通过键可以快速找到对应的值。
- 快速访问:HashMap通过哈希表实现,它提供了常数时间复杂度(O(1))的查找、插入和删除操作,使得数据访问非常高效。
- 允许一个键为null:HashMap允许使用一个null键和多个null值。null键只能有一个,因为键的唯一性要求。
- 非线程安全:HashMap不是线程安全的,如果多个线程同时访问HashMap,并且至少有一个线程修改了映射,则必须保持外部同步。
- 初始容量和负载因子:HashMap有两个重要的参数,初始容量和负载因子。初始容量是哈希表创建时的容量,负载因子是哈希表在其容量自动增加之前可以达到多满的一种度量。这两个参数可以影响HashMap的性能。
(2)常用方法
① 构造函数
- HashMap(): 创建一个默认初始容量为16(必须是2的幂)和默认加载因子为0.75的空HashMap。
- HashMap(int initialCapacity): 创建一个指定初始容量的HashMap,加载因子为0.75。
- HashMap(int initialCapacity, float loadFactor): 创建一个指定初始容量和加载因子的HashMap。
- HashMap(Map<? extends K, ? extends V> m): 创建一个包含指定映射的HashMap。
② 增删改查和遍历
- put(K key, V value): 添加键值对到HashMap中。
- remove(Object key): 删除指定键的键值对。
- replace(K key, V value): 替换指定键的值。
- get(Object key): 获取指定键的值。
- containsKey(Object key): 检查HashMap是否包含指定的键。
- containsValue(Object value): 检查HashMap是否包含指定的值。
- forEach(BiConsumer<? super K, ? super V> action): 对HashMap中的每个键值对执行给定的操作。
③ 获取key和value
- keySet(): 返回HashMap中所有键的视图集。
- values(): 返回HashMap中所有值的视图集。
- entrySet(): 返回HashMap中所有键值对的视图集。
④ Stream流
- keySet().stream(): 返回HashMap中键的Stream流。
- entrySet().stream(): 返回HashMap中键值对的Stream流。
⑤ 其他方法
- size(): 返回HashMap中的键值对数量。
- isEmpty(): 检查HashMap是否为空。
- clear(): 清空HashMap中的所有键值对。
- putAll(Map<? extends K, ? extends V> m): 将指定映射的所有键值对添加到HashMap中。
- clone(): 返回HashMap的一个浅拷贝。
- replaceAll(BiFunction<? super K, ? super V, ? extends V> function): 将HashMap中的每个键值对替换为给定函数的结果。
- compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): 尝试计算指定键的值。
- computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction): 如果指定键不存在,则尝试计算其值并插入。
- computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): 如果指定键存在,则尝试计算其值并替换。
(3)示例代码
java
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
// 构造函数示例
HashMap<String, Integer> fruitPrices = new HashMap<>();
HashMap<String, Integer> fruitPricesWithCapacity = new HashMap<>(32);
HashMap<String, Integer> fruitPricesWithCapacityAndLoadFactor = new HashMap<>(32, 0.8f);
HashMap<String, Integer> fruitPricesWithMap = new HashMap<>(Map.of("Apple", 2, "Banana", 5));
// 增删改查和遍历示例
fruitPrices.put("Apple", 2);
fruitPrices.put("Banana", 5);
fruitPrices.put("Cherry", 10);
fruitPrices.remove("Banana");
fruitPrices.replace("Apple", 10);
Integer applePrice = fruitPrices.get("Apple");
boolean hasApple = fruitPrices.containsKey("Apple");
boolean hasPrice = fruitPrices.containsValue(10);
fruitPrices.forEach((fruit, price) -> System.out.println(fruit + "的价格是:" + price));
// 获取key和value示例
System.out.println("所有的水果:" + fruitPrices.keySet());
System.out.println("所有水果的价格:" + fruitPrices.values());
// Stream流示例
System.out.println("所有水果名称的Stream流:" + fruitPrices.keySet().stream().collect(Collectors.toList()));
System.out.println("所有水果键值对的Stream流:" + fruitPrices.entrySet().stream().collect(Collectors.toList()));
// 其他方法示例
int size = fruitPrices.size();
boolean isEmpty = fruitPrices.isEmpty();
fruitPrices.clear();
fruitPrices.putAll(Map.of("Apple", 2, "Banana", 5));
HashMap<String, Integer> clonedFruitPrices = (HashMap<String, Integer>) fruitPrices.clone();
fruitPrices.replaceAll((fruit, price) -> price + 1); // 每个价格加1
fruitPrices.compute("Apple", (fruit, price) -> price - 1); // Apple的价格减1
fruitPrices.computeIfAbsent("Cherry", fruit -> 10);
fruitPrices.computeIfPresent("Banana", (fruit, price) -> price + 2); // Banana的价格加2
// 遍历方法示例
System.out.println("使用for循环遍历:");
for (Map.Entry<String, Integer> entry : fruitPrices.entrySet()) {
System.out.println(entry.getKey() + "的价格是:" + entry.getValue());
}
System.out.println("使用增强for循环遍历:");
for (String fruit : fruitPrices.keySet()) {
System.out.println(fruit + "的价格是:" + fruitPrices.get(fruit));
}
// 根据key查询和修改value示例
System.out.println("修改前Apple的价格:" + fruitPrices.get("Apple"));
fruitPrices.put("Apple", 5);
System.out.println("修改后Apple的价格:" + fruitPrices.get("Apple"));
}
}
三、集合练习
1. ArrayList
(1)定义一个ArrayList,并添加以下元素:1, 2, 3, 4, 5。然后使用循环遍历并打印所有元素。
java
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> arr = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
arr.add(i);
}
for(Integer a :arr){
System.out.print(a+" ");//1 2 3 4 5
}
System.out.println();
arr.forEach(s-> System.out.print(s+" "));//1 2 3 4 5
System.out.println();
//System.out.println(arr);
}
}
(2)移除索引为2的元素,并输出修改后的ArrayList。
java
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
ArrayList<String> fruitList = new ArrayList<>();
fruitList.add("apple");
fruitList.add("banana");
fruitList.add("cherry");
fruitList.add("date");
fruitList.add("fig");
fruitList.remove("cherry");
//fruitList.remove(2); //或移除2号索引
System.out.println(fruitList); //[apple, banana, date, fig]
}
}
(3)给定一个包含整数的ArrayList,编写一个方法来计算所有元素的和。
java
import java.util.ArrayList;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i <= 100; i++) {
list.add(i);
}
// 方法一:
Integer sum1 = 0;
for (Integer i : list) {
sum1 += i;
}
System.out.println(sum1); // 5050
// 方法二:
int sum2 = list.stream().mapToInt(Integer::intValue).sum();
System.out.println(sum2); // 5050
}
}
(4)给定一个包含字符串的ArrayList,编写一个方法来删除所有包含字母"b"的字符串。
java
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(
List.of("apple", "banana", "watermelon", "peach", "strawberry")
);
list.removeIf(s -> s.contains("b"));
System.out.println(list);// [apple, watermelon, peach]
}
}
(5)将ArrayList反转,并输出反转后的ArrayList。(使用Collections)
java
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
ArrayList<String> fruitList = new ArrayList<>();
fruitList.add("apple");
fruitList.add("banana");
fruitList.add("cherry");
fruitList.add("date");
fruitList.add("fig");
Collections.reverse(fruitList);
System.out.println(fruitList); //[fig, date, cherry, banana, apple]
}
}
(6)给定一个包含整数的ArrayList,编写一个方法来找出最大的元素。
java
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.OptionalInt;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(
List.of(1, 3, 5, 7, 9, 10)
);
//方法一
Integer MAX1 = Integer.MIN_VALUE;
for (Integer i : list) {
if (MAX1 < i) {
MAX1 = i;
}
}
System.out.println(MAX1); // 10
//方法二
Optional<Integer> MAX2 = list.stream().max(Integer::compareTo);
MAX2.ifPresent(System.out::println); // 10
//方法三
OptionalInt MAX3 = list.stream().mapToInt(Integer::intValue).max();
MAX3.ifPresent(System.out::println); // 10
}
}
(7)给定两个包含整数的ArrayList,编写一个方法来合并这两个ArrayList,并去除重复元素,并进行排序。
java
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<>(
List.of(1, 3, 5, 7, 9, 10)
);
ArrayList<Integer> list2 = new ArrayList<>(
List.of(1, 2, 3, 4, 5, 6)
);
// 方法一
TreeSet<Integer> set = new TreeSet<>();
set.addAll(list1);
set.addAll(list2);
ArrayList<Integer> arr1 = new ArrayList<>(set);
System.out.println(arr1); // [1, 2, 3, 4, 5, 6, 7, 9, 10]
// 方法二
List<Integer> collect = Stream.concat(list1.stream(), list2.stream())
.distinct()
.sorted()
.collect(Collectors.toList());
ArrayList<Integer> arr2 = (ArrayList<Integer>) collect; // 向下转型 List<> -> ArrayList<>
System.out.println(arr2); // [1, 2, 3, 4, 5, 6, 7, 9, 10]
}
}
(8)给定一个整型ArrayList {10, 20, 30, 40, 50},请找出数字30的索引位置,并输出结果。
java
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(
List.of(10, 20, 30, 40, 50)
);
System.out.println(list.indexOf(30)); //2
}
}
(9)给定一个整型ArrayList {1, 2, 3, 4, 5},将其每个元素乘以2,并输出结果。
java
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>(
Arrays.asList(1, 2, 3, 4, 5)
);
// 方法一
for (int i = 0; i < numbers.size(); i++) {
numbers.set(i, numbers.get(i) * 2);
}
System.out.println(numbers);
// 方法二
List<Integer> collect = numbers.stream().map(s -> s * 2).collect(Collectors.toList());
System.out.println(collect);
}
}
(10)Collections练习
java
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
// 练习题1:创建一个包含5个整数的ArrayList,并输出
List<Integer> list1 = new ArrayList<>();
list1.add(1);
list1.add(2);
list1.add(3);
list1.add(4);
list1.add(5);
System.out.println("练习题1:输出ArrayList:" + list1); // 练习题1的输出:[1, 2, 3, 4, 5]
// 练习题2:使用Collections.sort()对ArrayList进行排序
Collections.sort(list1);
System.out.println("练习题2:升序排序后的ArrayList:" + list1); // 练习题2的输出:[1, 2, 3, 4, 5]
Collections.sort(list1, Collections.reverseOrder());
System.out.println("练习题2:降序排序后的ArrayList:" + list1); // 练习题2的输出:[5, 4, 3, 2, 1]
// 练习题3:使用Collections.reverse()对ArrayList进行反转
Collections.reverse(list1);
System.out.println("练习题3:反转后的ArrayList:" + list1); // 练习题3的输出:[1, 2, 3, 4, 5]
// 练习题4:使用Collections.shuffle()对ArrayList进行随机排序
Collections.shuffle(list1);
System.out.println("练习题4:随机排序后的ArrayList:" + list1); // 练习题4的输出:[随机顺序的元素]
// 练习题5:使用Collections.min()找出ArrayList中的最小值
System.out.println("练习题5:ArrayList中的最小值:" + Collections.min(list1)); // 练习题5的输出:1
// 练习题6:使用Collections.max()找出ArrayList中的最大值
System.out.println("练习题6:ArrayList中的最大值:" + Collections.max(list1)); // 练习题6的输出:5
// 练习题7:使用Collections.fill()将ArrayList中的所有元素替换为一个指定的值
Collections.fill(list1, 10);
System.out.println("练习题7:替换后的ArrayList:" + list1); // 练习题7的输出:[10, 10, 10, 10, 10]
// 练习题8:使用Collections.binarySearch()在已排序的ArrayList中查找一个元素
Collections.sort(list1);
System.out.println("练习题8:元素10在ArrayList中的位置:" + Collections.binarySearch(list1, 10)); // 练习题8的输出:2
// 练习题9:使用Collections.indexOfSubList()查找子列表在ArrayList中的位置
List<Integer> sublist = new ArrayList<>();
sublist.add(10);
sublist.add(10);
System.out.println("练习题9:子列表在ArrayList中的位置:" + Collections.indexOfSubList(list1, sublist)); // 练习题9的输出:-1(因为子列表长度不匹配)
// 练习题10:使用Collections.lastIndexOfSubList()查找子列表在ArrayList中最后一次出现的位置
System.out.println("练习题10:子列表在ArrayList中最后一次出现的位置:" + Collections.lastIndexOfSubList(list1, sublist)); // 练习题10的输出:3
// 练习题11:使用Collections.replaceAll()将ArrayList中的某个元素替换为另一个元素
Collections.replaceAll(list1, 10, 20);
System.out.println("练习题11:替换后的ArrayList:" + list1); // 练习题11的输出:[20, 20, 20, 20, 20]
// 练习题12:使用Collections.frequency()统计ArrayList中某个元素出现的次数
System.out.println("练习题12:元素20在ArrayList中出现的次数:" + Collections.frequency(list1, 20)); // 练习题12的输出:5
// 练习题13:使用Collections.emptyList()创建一个空的ArrayList
List<Integer> emptyList = Collections.emptyList();
System.out.println("练习题13:空的ArrayList:" + emptyList); // 练习题13的输出:[]
// 练习题14:使用Collections.singletonList()创建一个只包含一个元素的ArrayList
List<Integer> singleList = Collections.singletonList(30);
System.out.println("练习题14:只包含一个元素的ArrayList:" + singleList); // 练习题14的输出:[30]
// 练习题15:使用Collections.synchronizedList()创建一个线程安全的ArrayList
List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
synchronizedList.add(40);
System.out.println("练习题15:线程安全的ArrayList:" + synchronizedList); // 练习题15的输出:[40]
}
}
2. HashSet
(11)判断HashSet中是否包含某个元素。
java
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Cherry");
boolean contains = hashSet.contains("Banana");
System.out.println(contains); //true
}
}
(12)从HashSet中删除一个元素,并输出删除后的HashSet。
java
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Cherry");
hashSet.remove("Banana");
System.out.println(hashSet);
}
}
(13)遍历HashSet中的所有元素。
java
import java.util.HashSet;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
HashSet<String> hashSet = new HashSet<>();
hashSet.add("Apple");
hashSet.add("Banana");
hashSet.add("Cherry");
Iterator<String> iterator = hashSet.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
System.out.println();
for (String i : hashSet) {
System.out.print(i + " ");
}
System.out.println();
hashSet.forEach(s -> System.out.print(s + " "));
System.out.println();
}
}
(14)创建一个HashSet,移除所有偶数。
java
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
HashSet<Integer> hashSet = new HashSet<>(
Set.of(1, 2, 3, 4, 5, 2)
);
// 方法一
hashSet.removeIf(e -> e % 2 == 0);
System.out.println(hashSet);
// 方法二
Iterator<Integer> iterator = hashSet.iterator();
while (iterator.hasNext()) {
Integer e = iterator.next();
if (e % 2 == 0) {
// 不能写 hashSet.remove(e);
// 不能在迭代器迭代过程中直接修改集合(例如使用remove方法)
// 否则会抛出ConcurrentModificationException异常。
// 这是因为迭代器依赖于集合的内部状态,
// 而直接修改集合会破坏这种状态。
iterator.remove();
}
}
System.out.println(hashSet);
}
}
(15)给定两个HashSet,创建一个方法来计算它们的并集。
java
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
HashSet<Integer> set1 = new HashSet<>(Set.of(1, 2, 3));
HashSet<Integer> set2 = new HashSet<>(Set.of(3, 4, 5));
HashSet<Integer> Union = new HashSet<>(set1);
Union.addAll(set2);
System.out.println(Union);
HashSet<Integer> collect = Stream.concat(set1.stream(), set2.stream())
.collect(Collectors.toCollection(HashSet::new));
System.out.println(collect);
}
}
(16)给定一个整数数组,去除重复元素,并按降序排列。
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Integer[] arr = {1, 2, 2, 2, 3, 3, 4, 5, 6};
TreeSet<Integer> integers = new TreeSet<>(Collections.reverseOrder());
integers.addAll(Arrays.asList(arr));
System.out.println(integers);
}
}
3. HashMap
(17)创建一个HashMap,并添加5个键值对,然后遍历并打印所有键值对。
java
import java.util.*;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Cherry", 3);
map.put("Date", 4);
map.put("Elderberry", 5);
// 方式一
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> en : entries) {
System.out.println(en.getKey() + ":" + en.getValue());
}
System.out.println();
// 方式二
Set<String> keys = map.keySet();
for (var key : keys) {
System.out.println(key + ":" + map.get(key));
}
System.out.println();
// 方式三
map.forEach((key, value) -> System.out.println(key + ":" + value));
}
}
(18)检查HashMap中是否包含某个键或值?
java
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Cherry", 3);
// 检查键
if (map.containsKey("Apple")) {
System.out.println("Key 'Apple' exists.");
} else {
System.out.println("Key 'Apple' does not exist.");
}
// 检查值
if (map.containsValue(3)) {
System.out.println("Value 3 exists.");
} else {
System.out.println("Value 3 does not exist.");
}
}
}
(19)从HashMap中删除所有值为null的键值对。
java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("a", "apple");
map.put("b", null);
map.put("c", "cherry");
map.values().removeIf(value -> value == null);
System.out.println(map);
}
}
(20)给定一个整数数组,找出数组中每个元素对应出现次数。
java
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 2, 1, 3, 4, 5, 4, 6};
Map<Integer, Integer> countMap1 = new HashMap<>();
// 方法一
for (int number : numbers) {
//getOrDefault(a,b)如果key含有a那么就取出a的值,否则就取出b
countMap1.put(number, countMap1.getOrDefault(number, 0) + 1);
}
System.out.println(countMap1); //{1=2, 2=2, 3=2, 4=2, 5=1, 6=1}
// 方法二
Map<Integer, Long> countMap2 = IntStream.of(numbers)
.boxed() // 将int转换为Integer
.collect(Collectors.groupingBy(
e -> e, // 分组的键
Collectors.counting() // 计算每个键的出现次数
));
System.out.println(countMap2); // 输出:{1=2, 2=2, 3=2, 4=2, 5=1, 6=1}
}
}
(21)合并两个HashMap,如果键相同,则将对应的值相加。
java
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map1 = Map.of("a", 1, "b", 2);
Map<String, Integer> map2 = Map.of("a", 3, "c", 4);
Map<String, Integer> result = new HashMap<>(map1);
map2.forEach((key, value) -> result.merge(key, value, Integer::sum));
System.out.println(result); // 输出:{a=4, b=2, c=4}
}
}
(22)反转HashMap中的键和值。
java
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<String, Integer> originalMap = new HashMap<>();
originalMap.put("one", 1);
originalMap.put("two", 2);
originalMap.put("three", 3);
Map<Integer, String> collect = originalMap.entrySet().stream()
.collect(Collectors.toMap(e -> e.getValue(), e -> e.getKey()));
System.out.println(collect);
}
}
(23)将一个整数数组中的元素按照其出现的次数降序排序。
java
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
public static List<Integer> sortByFrequency(int[] nums) {
Map<Integer, Long> frequencyMap = Arrays.stream(nums)
.boxed()
.collect(Collectors.groupingBy(e -> e, Collectors.counting()));
return Arrays.stream(nums)
.boxed()
.sorted((a, b) -> frequencyMap.get(b).intValue() - frequencyMap.get(a).intValue())
.collect(Collectors.toList());
}
public static void main(String[] args) {
int[] nums = {1, 1, 1, 2, 2, 2, 3, 3, 4};
System.out.println(sortByFrequency(nums)); // 输出:[1, 1, 1, 2, 2, 2, 3, 3, 4]
}
}
(24)找出两个HashMap中共有的键(键的交集)。
java
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map1 = new HashMap<>(
Map.of("a", 1, "b", 2, "c", 3)
);
Map<String, Integer> map2 = new HashMap<>(
Map.of("b", 2, "c", 3, "d", 4)
);
List<String> collect = map2.keySet().stream()
.filter(s -> map1.containsKey(s))
.collect(Collectors.toList());
System.out.println(collect);
}
}
(25)输出一个Map中最小和最大的Key。
java
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(1, "One");
treeMap.put(3, "Three");
treeMap.put(2, "Two");
System.out.println("First Key: " + treeMap.firstKey());
System.out.println("Last Key: " + treeMap.lastKey());
}
}
// 输出:
// First Key: 1
// Last Key: 3