2009-10-12 3 views
2

값 비싼 계산 결과를 캐시에 저장하고 싶습니다. 두 개의 키가있는지도를 만들 수있는 방법이 있습니까? 나는 Map<(Thing1, Thing2), Integer>과 같은 것을 생각하고있다. Java : 계산 결과 캐싱을위한 데이터 구조?

은 그럼 확인할 수 있습니다 :

if (! cache.contains(thing1, thing2)) { 
    return computeResult(); 
} 
else { 
    return cache.getValue(thing1, thing2); 
} 

의사를. 그러나 그 라인을 따라 뭔가.

답변

5

당신은 Thing1 및 Thing2를 보유하는 클래스를 작성해야합니다 예 :

class Things { 
    public final Thing1 thing1; 
    public final Thing2 thing2; 
    public Things(Thing1 thing1, Thing2 thing2) { 
     this.thing1 = thing1; 
     this.thing2 = thing2; 
    } 
    @Override 
    public boolean equals(Object obj) { ... } 
    @Override 
    public int hashCode() { ... }; 
} 

그런 다음이 기능을 사용하려면

Things key = new Things(thing1, thing2); 
if (!cache.contains(key) { 
    Integer result = computeResult(); 
    cache.put(key, result); 
    return result; 
} else { 
    return cache.getValue(key); 
} 

참고이 코드가 작동 할 등호 및 해시 코드를 구현해야 정확히. 이 코드가 쓰레드 - 안전 할 필요가 있다면 ConcurrentHashMap을 보라.

+0

무시 무시한 ... 나는 * 단지 * 5 분 전에 이것을 했으므로 다음과 같이이 질문을 보았습니다 ... hashCode 메서드의 구현을 권장합니다 (이것은 기본 일식 구현입니다). (31 + thing1.hashCode()) * 31 + thing2.hashCode();' – Kip

+1

@Kip : 사실, Apache Commons Lang의'HashCodeBuilder','EqualsBuilder','CompareToBuilder'를 사용하는 것이 좋습니다. :-) –

+0

이 프로그램을 구현하는 데 10 분 미만의 시간이 걸렸으며 지금은 25 %의 시간 동안 프로그램이 실행됩니다. 와우. –

2

Google Collections을 사용하는 경우 해당 MapMaker 클래스는 사용자가 설명한 것과 정확히 일치하는 makeComputingMap 메서드를 사용합니다. 무료 보너스로 스레드로부터 안전합니다 (ConcurrentMap 구현).

두 키 점에 관해서는, 당신은 (해당하는 경우) 키 비교 당신이 원하는 방식으로 수행 compareTo을 두 개의 키를 포함하는 클래스를 확인해야하고, equals, hashCode의 적절한 구현을 구현하는 것 그것.

+0

저는 모두 Google Collections에 대한 것이지만 어떻게 작동하는지 이해하는 데 어려움을 겪고 있습니다. –

+0

기본적으로'computeResult' 함수를 호출하는'Function' 객체를 만듭니다.Google 객체는지도에서 적절한 항목을 가져올 때 해당 함수를 호출하고 값을 캐싱합니다. :-) –

3

메모를 원한다는 소리가납니다. Functional Java의 최신 트렁크 헤드에는 결과가 캐싱 된 계산을 모델링하는 memoising 제품 유형 P1이 있습니다.

당신은 다음과 같이 사용합니다 :

비싼 계산을 실행하고 메모에 저장됩니다 _1()를 처음 호출
P1<Thing> myThing = new P1<Thing>() { 
    public Thing _1() { 
    return expensiveComputation(); 
    } 
}.memo(); 

. 그 후 메모가 대신 반환됩니다.

"두 개의 키"에 대해 간단한 쌍 유형을 원할 수 있습니다. 기능 Java는 클래스 P2<A, B>의 형태로도 이것을 가지고 있습니다. 이러한 값을 메모하려면 단순히 P1<P2<A, B>>을 사용하십시오.

memoisation 대신 Promise<A> 클래스를 사용할 수도 있습니다. 이것은 잠시 동안 도서관에 있었기 때문에 최신 바이너리가 필요할 것입니다. 다음과 같이 사용하십시오 :

Promise<Thing> myThing = 
    parModule(sequentialStrategy).promise(new P1<Thing>() { 
    public Thing _1() { 
     return expensiveComputation(); 
    } 
    }); 

결과를 얻으려면 myThing.claim()으로 전화하십시오. Promise<A>은 결과가 아직 준비되지 않은 경우에도 이상의 함수를 매핑하는 방법을 제공합니다..

import static fj.control.parallel.ParModule.parModulefj.control.parallel.Strategy.sequentialStrategy이 필요합니다. 계산을 자체 스레드에서 실행하려면 sequentialStrategyStrategy 클래스가 제공하는 다른 전략 중 하나로 바꾸십시오.