Map의 keySet () 및 entrySet ()에 대한 성능 고려 사항
모두,
누구든지 2 사이의 성능 문제가 무엇인지 정확히 알려 주실 수 있습니까? 사이트 : CodeRanch 는 keySet () 및 get ()을 사용할 때 필요한 내부 호출에 대한 간략한 개요를 제공합니다. 그러나 keySet () 및 get () 메서드를 사용할 때 누구든지 흐름에 대한 정확한 세부 정보를 제공 할 수 있다면 좋을 것입니다. 이것은 성능 문제를 더 잘 이해하는 데 도움이 될 것입니다.
우선, 이것은 전적으로 사용중인지도 유형에 따라 다릅니다. 그러나 JavaRanch 스레드가 HashMap에 대해 이야기하기 때문에 이것이 당신이 언급하는 구현이라고 가정하겠습니다. 또한 Sun / Oracle의 표준 API 구현에 대해 이야기하고 있다고 가정 해 보겠습니다.
둘째, 해시 맵을 반복 할 때 성능이 염려된다면 LinkedHashMap
. 문서에서 :
LinkedHashMap의 컬렉션 뷰를 반복하려면 용량에 관계없이 맵 크기에 비례하는 시간이 필요합니다. HashMap을 통한 반복은 비용이 더 많이 들고 용량에 비례하는 시간이 필요합니다.
HashMap.entrySet ()
이 구현의 소스 코드를 사용할 수 있습니다. 구현은 기본적으로 새로운 HashMap.EntrySet
. 다음과 같은 클래스 :
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return newEntryIterator(); // returns a HashIterator...
}
// ...
}
그리고 HashIterator
외모가 좋아
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; // next entry to return
int expectedModCount; // For fast-fail
int index; // current slot
Entry<K,V> current; // current entry
HashIterator() {
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
}
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
if ((next = e.next) == null) {
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
current = e;
return e;
}
// ...
}
그래서 당신은 그것을 가지고 있습니다 ... 그것은 entrySet을 반복 할 때 일어날 일을 지시하는 코드입니다. 맵 용량만큼 긴 전체 어레이를 안내합니다.
HashMap.keySet () 및 .get ()
Here you first need to get hold of the set of keys. This takes time proportional to the capacity of the map (as opposed to size for the LinkedHashMap). After this is done, you call get()
once for each key. Sure, in the average case, with a good hashCode-implementation this takes constant time. However, it will inevitably require lots of .hashCode
and .equals
calls, which will obviously take more time than just doing a entry.value()
call.
The most common case where using entrySet is preferable over keySet is when you are iterating through all of the key/value pairs in a Map.
This is more efficient:
for (Map.Entry entry : map.entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
}
than:
for (Object key : map.keySet()) {
Object value = map.get(key);
}
Because in the second case, for every key in the keySet the map.get()
method is called, which - in the case of a HashMap - requires that the hashCode()
and equals()
methods of the key object be evaluated in order to find the associated value*. In the first case that extra work is eliminated.
Edit: This is even worse if you consider a TreeMap, where a call to get is O(log2(n)), i.e. the comparator for will may need to run log2(n) times (n = size of the Map) before finding the associated value.
*Some Map implementations have internal optimisations that check the objects' identity before the hashCode()
and equals()
are called.
Here is the link to an article comparing the performance of entrySet()
, keySet()
and values()
, and advice regarding when to use each approach.
Apparently the use of keySet()
is faster (besides being more convenient) than entrySet()
as long as you don't need to Map.get()
the values.
'IT TIP' 카테고리의 다른 글
내용을 기반으로 문자열 목록 필터링 (0) | 2020.10.23 |
---|---|
':'문자, 16 진수 값 0x3A는 이름에 포함될 수 없습니다. (0) | 2020.10.23 |
전체 복사, 얕은 복사, 복제 (0) | 2020.10.23 |
IIS에서 .svc 파일에 액세스 할 때 HTTP 404 (0) | 2020.10.22 |
jQuery DataTables : 3 개의 문자를 입력하거나 버튼을 클릭 할 때까지 검색 지연 (0) | 2020.10.22 |