Map之computeIfAbsent使用解讀
Map之computeIfAbsent
在Java編程中,Map接口提供了一個便捷的方法computeIfAbsent,它可以用來從map中獲取key對應(yīng)的value。如果value不存在,就使用提供的Function創(chuàng)建一個新的value,然后存入map中,最后返回這個新創(chuàng)建的value
computeIfAbsent方法是Java 8中引入的一種簡化操作Map的方式。該方法通過自動檢查鍵值對是否存在并生成缺失的值,減少了手動檢查和插入的樣板代碼。它不僅使代碼更加簡潔和易讀,還提高了操作的效率和一致性。
computeIfAbsent 方法的簡介
computeIfAbsent方法在Java 8中引入,用于簡化在Map中獲取值的操作。
如果指定的鍵在Map中不存在,computeIfAbsent會調(diào)用指定的函數(shù)來生成一個新的值,并將其與鍵關(guān)聯(lián)。
這樣,開發(fā)者不需要顯式地檢查鍵是否存在,從而減少了樣板代碼。
方法簽名
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
參數(shù)說明
key:要在map中查找的鍵。mappingFunction:用于生成默認(rèn)值的函數(shù)。
返回值
- 如果
key已經(jīng)存在于map中,則返回對應(yīng)的value。 - 如果
key不存在于map中,則使用mappingFunction生成一個新value,存入map,并返回這個新value。
示例
優(yōu)化前的代碼
在沒有使用computeIfAbsent方法之前,我們通常會這樣寫:
Map<String, Set<Pet>> statistics = new HashMap<>();
Set<Pet> pets = statistics.get(threadName);
if (pets == null) {
pets = new HashSet<>();
statistics.put(threadName, pets);
}優(yōu)化后的代碼
使用computeIfAbsent方法后,代碼變得更加簡潔和易讀:
Map<String, Set<Pet>> statistics = new HashMap<>(); Set<Pet> pets = statistics.computeIfAbsent(threadName, k -> new HashSet<>());
工作原理
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}詳細(xì)解釋
- 檢查現(xiàn)有值:首先檢查指定的鍵是否已經(jīng)存在于map中。
- 生成新值:如果鍵不存在,使用
mappingFunction生成一個新的值。 - 存儲新值:將新生成的值與鍵關(guān)聯(lián)并存儲在map中。
- 返回值:返回與鍵關(guān)聯(lián)的值(新生成的或已存在的)。
實際應(yīng)用中的示例
示例1:統(tǒng)計單詞出現(xiàn)的次數(shù)
我們有一個文本,想統(tǒng)計每個單詞出現(xiàn)的次數(shù)。我們可以使用computeIfAbsent方法來簡化統(tǒng)計邏輯:
import java.util.*;
public class WordCounter {
public static void main(String[] args) {
String text = "hello world hello Java hello world";
String[] words = text.split(" ");
Map<String, Integer> wordCount = new HashMap<>();
for (String word : words) {
wordCount.computeIfAbsent(word, k -> 0);
wordCount.put(word, wordCount.get(word) + 1);
}
wordCount.forEach((k, v) -> System.out.println(k + ": " + v));
}
}在這個例子中,computeIfAbsent方法確保每個單詞在第一次出現(xiàn)時被初始化為0,然后我們簡單地增加計數(shù)值。
示例2:分組學(xué)生名單
假設(shè)我們有一組學(xué)生的成績記錄,我們想按分?jǐn)?shù)段對學(xué)生進(jìn)行分組。例如,分?jǐn)?shù)在90以上的分為一組,80-89分為一組,依此類推。
我們可以使用computeIfAbsent方法來實現(xiàn)這個功能:
import java.util.*;
public class StudentGrouper {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("Alice", 85),
new Student("Bob", 92),
new Student("Charlie", 87),
new Student("David", 72),
new Student("Eve", 90)
);
Map<String, List<String>> gradeGroups = new HashMap<>();
for (Student student : students) {
String gradeCategory = getGradeCategory(student.getScore());
gradeGroups.computeIfAbsent(gradeCategory, k -> new ArrayList<>()).add(student.getName());
}
gradeGroups.forEach((k, v) -> System.out.println(k + ": " + v));
}
public static String getGradeCategory(int score) {
if (score >= 90) {
return "90-100";
} else if (score >= 80) {
return "80-89";
} else if (score >= 70) {
return "70-79";
} else {
return "Below 70";
}
}
}
class Student {
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public String getName() {
return name;
}
public int getScore() {
return score;
}
}在這個示例中,computeIfAbsent方法確保每個分?jǐn)?shù)段(例如“90-100”)被正確初始化為一個新的ArrayList,然后我們將學(xué)生的名字添加到對應(yīng)的分組中。
示例3:構(gòu)建依賴圖
假設(shè)我們有一組任務(wù),每個任務(wù)可能依賴于其他任務(wù)。我們希望構(gòu)建一個依賴圖,表示每個任務(wù)的依賴關(guān)系。我們可以使用computeIfAbsent方法來簡化圖的構(gòu)建:
import java.util.*;
public class DependencyGraph {
public static void main(String[] args) {
Map<String, List<String>> dependencies = new HashMap<>();
addDependency(dependencies, "Task1", "Task2");
addDependency(dependencies, "Task1", "Task3");
addDependency(dependencies, "Task2", "Task4");
addDependency(dependencies, "Task3", "Task4");
addDependency(dependencies, "Task4", "Task5");
dependencies.forEach((k, v) -> System.out.println(k + " depends on " + v));
}
public static void addDependency(Map<String, List<String>> dependencies, String task, String dependency) {
dependencies.computeIfAbsent(task, k -> new ArrayList<>()).add(dependency);
}
}在這個示例中,computeIfAbsent方法確保每個任務(wù)都有一個對應(yīng)的依賴列表。如果任務(wù)不存在,則初始化一個新的ArrayList并添加依賴關(guān)系。
示例4:緩存計算結(jié)果
在某些場景中,計算某些值可能非常耗時,因此我們希望緩存計算結(jié)果以提高效率。我們可以使用computeIfAbsent方法來實現(xiàn)簡單的緩存:
import java.util.*;
public class FibonacciCache {
private static Map<Integer, Integer> cache = new HashMap<>();
public static void main(String[] args) {
System.out.println(fibonacci(10)); // 輸出:55
System.out.println(fibonacci(20)); // 輸出:6765
System.out.println(fibonacci(30)); // 輸出:832040
}
public static int fibonacci(int n) {
if (n <= 1) {
return n;
}
return cache.computeIfAbsent(n, k -> fibonacci(k - 1) + fibonacci(k - 2));
}
}在這個示例中,computeIfAbsent方法用于緩存斐波那契數(shù)列的計算結(jié)果。對于每一個n,如果緩存中不存在對應(yīng)的值,則進(jìn)行計算并緩存結(jié)果。這種方法大大提高了計算效率,避免了重復(fù)計算。
優(yōu)勢總結(jié)
使用computeIfAbsent方法有以下幾個優(yōu)勢:
- 簡潔性:減少了樣板代碼,使代碼更加簡潔和易讀。
- 避免重復(fù)代碼:通過使用
computeIfAbsent方法,我們避免了顯式的空檢查和插入邏輯。 - 線程安全性:對于某些并發(fā)Map實現(xiàn)(如
ConcurrentHashMap),computeIfAbsent提供了線程安全的方式來處理映射關(guān)系。 - 性能提升:在需要緩存計算結(jié)果或避免重復(fù)計算的場景中,
computeIfAbsent可以顯著提高性能。 - 代碼一致性:通過使用
computeIfAbsent,代碼更加一致和規(guī)范,易于維護(hù)。
通過理解和使用computeIfAbsent方法,開發(fā)者可以寫出更簡潔、易讀且高效的代碼,使得在操作map時更加得心應(yīng)手。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于Java實現(xiàn)楊輝三角 LeetCode Pascal''s Triangle
這篇文章主要介紹了基于Java實現(xiàn)楊輝三角 LeetCode Pascal's Triangle的相關(guān)資料,需要的朋友可以參考下2016-01-01
基于Java實現(xiàn)EWMA指數(shù)加權(quán)移動平均模型
指數(shù)加權(quán)移動平均(EWMA)是一種常用的時間序列分析方法,與傳統(tǒng)的簡單移動平均相比,EWMA賦予最近的數(shù)據(jù)點更高的權(quán)重,從而能夠更快地響應(yīng)數(shù)據(jù)的變化,本文將介紹EWMA的基本原理,并提供一個簡單的Java實現(xiàn)示例,需要的朋友可以參考下2025-05-05

