일부 테스트 결과
나는이 질문에 많은 좋은 답변을 얻었습니다. 감사합니다. 그래서 몇 가지 테스트를 실행하고 실제로 가장 빠른 방법을 결정하기로 결정했습니다. 내가 테스트 한 5 가지 방법은 다음과 같습니다.
- 질문에 제시 한 "ContainsKey"방법
- Aleksandar Dimitrov가 제안한 "TestForNull"메소드
- Hank Gay가 제안한 "AtomicLong"방법
- jrudolph가 제안한 "Trove"방법
- phax.myopenid.com에서 제안한 "MutableInt"방법
방법
여기 내가 한 일이 있습니다 ...
- 아래 표시된 차이점을 제외하고 동일한 5 개의 클래스를 작성했습니다. 각 클래스는 내가 제시 한 시나리오, 즉 10MB 파일을 열고 읽은 다음 파일의 모든 단어 토큰의 빈도 수를 수행하는 일반적인 작업을 수행해야했습니다. 이 작업에는 평균 3 초 밖에 걸리지 않았으므로 I / O가 아닌 주파수 카운트를 10 회 수행했습니다.
- 10 회 반복을 반복했지만 I / O 작업은 수행하지 않았 으며 Java Cookbook에서 Ian Darwin의 방법을 사용하여 취한 총 시간 (시계 초)을 기록했습니다 .
- 다섯 가지 테스트를 모두 연속으로 수행 한 다음이 작업을 세 번 더 수행했습니다.
- 각 방법에 대해 4 개의 결과를 평균했습니다.
결과
먼저 관심있는 사람들을 위해 결과와 아래 코드를 제시하겠습니다.
ContainsKey의 나는 그 방법의 속도에 비해 각 방법의 속도를 줄 것이다, 그래서 방법은, 가장 느린을 예상한다.
- ContainsKey : 30.654 초 (기준)
- 원자 길이 : 29.780 초 (1.03 배 빠른 속도)
- TestForNull : 28.804 초 (1.06 배 빠른 속도)
- 트 로브 : 26.313 초 (1.16 배 빠른 속도)
- MutableInt : 25.747 초 (1.19 배 빠른 속도)
결론
MutableInt 방법과 Trove 방법 만 10 % 이상의 성능 향상을 제공한다는 점에서 훨씬 빠릅니다. 그러나 스레딩이 문제인 경우 AtomicLong이 다른 것보다 매력적일 수 있습니다 (확실하지는 않습니다). final
변수로 TestForNull을 실행 했지만 그 차이는 무시할 만했습니다.
다른 시나리오에서 메모리 사용량을 프로파일 링하지 않았습니다. MutableInt 및 Trove 메서드가 메모리 사용에 어떤 영향을 미칠지에 대한 통찰력이있는 사람이라면 누구나 기뻐할 것입니다.
개인적으로 MutableInt 메서드는 타사 클래스를로드 할 필요가 없으므로 가장 매력적입니다. 따라서 문제를 발견하지 않으면 내가 갈 가능성이 가장 큽니다.
코드
각 방법의 중요한 코드는 다음과 같습니다.
ContainsKey
import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
int count = freq.containsKey(word) ? freq.get(word) : 0;
freq.put(word, count + 1);
TestForNull
import java.util.HashMap;
import java.util.Map;
...
Map<String, Integer> freq = new HashMap<String, Integer>();
...
Integer count = freq.get(word);
if (count == null) {
freq.put(word, 1);
}
else {
freq.put(word, count + 1);
}
원자 긴
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
...
final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
...
map.putIfAbsent(word, new AtomicLong(0));
map.get(word).incrementAndGet();
트 로브
import gnu.trove.TObjectIntHashMap;
...
TObjectIntHashMap<String> freq = new TObjectIntHashMap<String>();
...
freq.adjustOrPutValue(word, 1, 1);
MutableInt
import java.util.HashMap;
import java.util.Map;
...
class MutableInt {
int value = 1; // note that we start at 1 since we're counting
public void increment () { ++value; }
public int get () { return value; }
}
...
Map<String, MutableInt> freq = new HashMap<String, MutableInt>();
...
MutableInt count = freq.get(word);
if (count == null) {
freq.put(word, new MutableInt());
}
else {
count.increment();
}