java Map的使用computeIfAbsent去重
Java 中 Map.computeIfAbsent() 方法可以用于去重场景,特别是当需要根据键生成复杂值或维护键对应的集合时。以下是几种常见用法:
1. 基础去重示例
JAVA
Map<String, String> map = new HashMap<>();
List<String> names = Arrays.asList("Alice", "Bob", "Alice", "Charlie", "Bob");
// 去重并标记首次出现
for (String name : names) {
map.computeIfAbsent(name, k -> "First seen: " + k);
}
// 结果: {Alice=First seen: Alice, Bob=First seen: Bob, Charlie=First seen: Charlie}
System.out.println(map);
2. 分组去重(一对多映射)
JAVA
Map<String, List<String>> groupMap = new HashMap<>();
String[][] data = {
{"Group1", "A"}, {"Group1", "B"},
{"Group2", "C"}, {"Group1", "A"} // 重复的 A
};
for (String[] pair : data) {
groupMap.computeIfAbsent(pair[0], k -> new ArrayList<>());
if (!groupMap.get(pair[0]).contains(pair[1])) {
groupMap.get(pair[0]).add(pair[1]);
}
}
// 结果: Group1=[A, B], Group2=[C]
3. 计数去重
JAVA
Map<String, Integer> countMap = new HashMap<>();
String[] words = {"apple", "banana", "apple", "orange", "banana", "banana"};
for (String word : words) {
countMap.computeIfAbsent(word, k -> 0);
countMap.put(word, countMap.get(word) + 1);
}
// 结果: {apple=2, banana=3, orange=1}
4. 对象属性去重
JAVA
class Person {
String id;
String name;
// 构造器、getter/setter
}
List<Person> persons = Arrays.asList(
new Person("1", "Alice"),
new Person("2", "Bob"),
new Person("1", "Alice") // 重复ID
);
Map<String, Person> personMap = new HashMap<>();
for (Person p : persons) {
personMap.computeIfAbsent(p.getId(), k -> p);
}
// 结果: 只有两个不重复的Person
5. 使用 ConcurrentHashMap 线程安全去重
JAVA
ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<>();
List<String> items = Arrays.asList("A", "B", "A", "C", "B");
items.parallelStream().forEach(item -> {
concurrentMap.computeIfAbsent(item, k -> "Processed: " + k);
});
6. 复杂值初始化示例
JAVA
Map<String, Set<Integer>> complexMap = new HashMap<>();
String[][] records = {
{"user1", "100"}, {"user1", "200"},
{"user2", "300"}, {"user1", "100"} // 重复
};
for (String[] record : records) {
complexMap.computeIfAbsent(record[0], k -> new HashSet<>())
.add(Integer.parseInt(record[1]));
}
// 结果: user1=[100, 200], user2=[300]
7. 与 Stream API 结合
JAVA
List<String> duplicates = Arrays.asList("a", "b", "a", "c", "b", "a");
// 获取首次出现的位置
Map<String, Integer> firstOccurrence = new HashMap<>();
for (int i = 0; i < duplicates.size(); i++) {
int index = i;
firstOccurrence.computeIfAbsent(duplicates.get(i), k -> index);
}
// 结果: {a=0, b=1, c=3}
关键点总结
computeIfAbsent方法签名:JAVAV computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)- 如果键不存在,使用函数计算值并存入
- 如果键存在,直接返回现有值
去重优势:
- 避免不必要的对象创建
- 代码更简洁,避免
if (!map.containsKey(key))检查 - 原子性操作(在 ConcurrentHashMap 中)
注意事项:
- 映射函数不应有副作用
- 在非并发映射中,非线程安全
- 映射函数返回
null时会抛出异常
这种方法特别适合需要初始化复杂值(如集合、对象)的去重场景。