나는 Map.computeIfAbsent 를 사용하고 싶지만 학부에서 람다 이후로 너무 오래되었습니다.
문서에서 거의 직접 : 작업을 수행하는 이전 방법의 예를 제공합니다.
Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
String key = "snoop";
if (whoLetDogsOut.get(key) == null) {
Boolean isLetOut = tryToLetOut(key);
if (isLetOut != null)
map.putIfAbsent(key, isLetOut);
}
그리고 새로운 방법 :
map.computeIfAbsent(key, k -> new Value(f(k)));
그러나 그들의 예에서 나는 “그것을 이해”하고 있지 않다고 생각합니다. 이것을 표현하는 새로운 람다 방식을 사용하도록 코드를 어떻게 변환할까요?
답변
다음 코드가 있다고 가정합니다.
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Test {
public static void main(String[] s) {
Map<String, Boolean> whoLetDogsOut = new ConcurrentHashMap<>();
whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
whoLetDogsOut.computeIfAbsent("snoop", k -> f(k));
}
static boolean f(String s) {
System.out.println("creating a value for \""+s+'"');
return s.isEmpty();
}
}
그러면 해당 키에 대한 값이 이미있는 creating a value for "snoop"
두 번째 호출 에서 메시지가 정확히 한 번만 표시됩니다 computeIfAbsent
. k
람다 표현은 k -> f(k)
바로지도가 값을 계산하기 위해 람다로 전달됩니다 키에 대한 placeolder (매개 변수)입니다. 따라서 예제에서 키는 함수 호출로 전달됩니다.
또는 다음과 같이 작성할 수 whoLetDogsOut.computeIfAbsent("snoop", k -> k.isEmpty());
있습니다. 도우미 메서드없이 동일한 결과를 얻을 수 있습니다 (하지만 디버깅 출력은 표시되지 않음). 또한 기존 메소드에 대한 간단한 위임이므로 더 간단합니다. whoLetDogsOut.computeIfAbsent("snoop", String::isEmpty);
이 위임은 매개 변수를 작성할 필요가 없습니다.
으로 가까운 예에 질문에 있으려면, 당신은 그것을 쓸 수 whoLetDogsOut.computeIfAbsent("snoop", key -> tryToLetOut(key));
(당신이 매개 변수의 이름을 여부를 중요하지 않습니다 k
또는 key
). 또는로 쓰는 whoLetDogsOut.computeIfAbsent("snoop", MyClass::tryToLetOut);
경우 tryToLetOut
입니다 static
또는 whoLetDogsOut.computeIfAbsent("snoop", this::tryToLetOut);
경우는 tryToLetOut
인스턴스 방법이다.
답변
최근에 저도이 방법을 가지고 놀았습니다. 나는 방법을 사용하는 방법에 대한 또 다른 예시가 될 수있는 피보나치 수를 계산하는 메모 알고리즘을 작성했습니다.
우리는지도를 정의하고 기본 경우에 그것의 값을 넣어 시작할 수 있습니다, 즉, fibonnaci(0)
및 fibonacci(1)
:
private static Map<Integer,Long> memo = new HashMap<>();
static {
memo.put(0,0L); //fibonacci(0)
memo.put(1,1L); //fibonacci(1)
}
귀납적 단계를 위해 우리가해야 할 일은 다음과 같이 피보나치 함수를 재정의하는 것입니다.
public static long fibonacci(int x) {
return memo.computeIfAbsent(x, n -> fibonacci(n-2) + fibonacci(n-1));
}
보시 computeIfAbsent
다시피이 메서드 는 제공된 람다 식을 사용하여 숫자가지도에 없을 때 피보나치 수를 계산합니다. 이는 기존의 트리 재귀 알고리즘에 비해 상당한 개선을 나타냅니다.
답변
다른 예시. 복잡한지도지도를 만들 때 computeIfAbsent () 메서드는지도의 get () 메서드를 대체합니다. computeIfAbsent () 호출을 함께 연결하면 누락 된 컨테이너가 제공된 람다 식에 의해 즉석에서 생성됩니다.
// Stores regional movie ratings
Map<String, Map<Integer, Set<String>>> regionalMovieRatings = new TreeMap<>();
// This will throw NullPointerException!
regionalMovieRatings.get("New York").get(5).add("Boyhood");
// This will work
regionalMovieRatings
.computeIfAbsent("New York", region -> new TreeMap<>())
.computeIfAbsent(5, rating -> new TreeSet<>())
.add("Boyhood");
답변
다중지도
당신이 만들 경우에 정말 유용 과 multimap을 받는 의지하지 않고 구글 구아바 의 구현을위한 라이브러리 MultiMap
.
예를 들어 특정 과목에 등록한 학생 목록을 저장한다고 가정합니다.
JDK 라이브러리를 사용하는 일반적인 솔루션은 다음과 같습니다.
Map<String,List<String>> studentListSubjectWise = new TreeMap<>();
List<String>lis = studentListSubjectWise.get("a");
if(lis == null) {
lis = new ArrayList<>();
}
lis.add("John");
//continue....
상용구 코드가 있기 때문에 사람들은 Guava를 사용하는 경향이 있습니다 Mutltimap
.
Map.computeIfAbsent를 사용하면 다음과 같이 guava Multimap없이 한 줄로 작성할 수 있습니다.
studentListSubjectWise.computeIfAbsent("a", (x -> new ArrayList<>())).add("John");
Stuart Marks와 Brian Goetz는 이것에 대해 좋은 이야기를했습니다.
https://www.youtube.com/watch?v=9uTVXxJjuco