2011-04-14 3 views
12

: 그렇게 있다면, 왜 자바, list.get (인덱스)의 목록과 같은 개체 액세스를 제공하지 않습니다
Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.LinkedHashMap에서 인덱스를 통한 액세스를 제공하지 않는 이유는 무엇입니까? 자바 독에서

;

UPDATE

내가의 LinkedHashMap을 사용하여 LRU 캐시를 구현했다. 내 알고리즘을 통해 캐시에서 LRU Object에 액세스해야했습니다. 그래서 무작위 액세스가 필요했는데 성능이 떨어질 것 같아서 로직을 변경했으며 캐시가 꽉 찼을 때 LRU 객체에 액세스하고 있습니다 ... removeEldestEntry() 사용

감사합니다. ..

답변

15

a) 항목이 연결되어있어 무작위로 액세스 할 수 없으므로. 내가 잘못하지 않으면 성능은 비참하다, O(N).

b)이 기능을 백업 할 인터페이스가 없으므로.

: 그래서 선택은 전용 단지 이것에 대한 인터페이스 (심하게 수행) 구현을 소개하는 일 수 또는 구현 클래스 대신 인터페이스 Guava와 Btw는


에 대해 프로그램 클라이언트를 필요로 당신을 위해 간단한 해결 방법이 있습니다

Iterables.get(map.values(), offset); 

캐싱의 경우 구아바의 MapMaker과 만료 기능을 살펴보십시오.

+0

감사합니다. 나는 LRU 캐시를 구현하기 위해 LinkedHashMap을 사용하고 있습니다 ... 그리고 LRU 객체를 들여다 볼 수있는 몇 가지 기능을 원했습니다 ... 그러나 맵을 반복하는 것은 매우 나쁜 성능이 될 것입니다 ... 그런 기능을위한 다른 데이터 구조를 알고 있습니까? –

+3

+1, 좋은 답변입니다. 그러나 LinkedList에서 제공하는 성능보다 더 나쁜 것은 아니므로 필자는 그 주장을 실제로 보지 못했다. – aioobe

+1

@Eternal Noob, 그것은 문서에서 다음과 같이 말합니다 : *이 종류의지도는 LRU 캐시를 구축하는 데 적합합니다. *, 그리고 *지도를 반복하는 것은 효율적입니다 (O (n)) – aioobe

1

이 인터페이스는 Iterator 인터페이스를 제공하며 목록의 각 노드는 이전 및 이후의 노드에 연결됩니다. get(i) 메서드를 사용하면 보조 배열이 없으므로 목록의 모든 요소를 ​​반복하는 것과 다를 바 없습니다 (LinkedList과 동일).

당신은 내가 values()이 값의 기가되는 콜렉션을 제공하기 때문에 자신이

+0

링크 된 목록에서 마지막 요소 인 list.get (list.size() - 1)에 액세스 할 때마다 임의 액세스 또는 O (n)입니다 (모든 요소가 반복)? –

+3

'It Iterator interface'가 올바르지 않습니다. 지도의 entrySet()은지도 자체가 아닌 반복자를 제공합니다 (그러나 당신이 맞다는 것을 제외하면) –

3
+3

이러한 맞춤 컬렉션을 아는 것은 좋은 일이지만 거의 유용하지 않습니다. 필요하다면 보통 코드에 디자인 결함이 있습니다 :-) –

+0

아파치 공유지에서 낚시를하는 동안 lru 맵에 대해 LRUMap을 시도하십시오. –

7

에서 봐 주시기 바랍니다지도를 확장하는 것이 좋습니다 매우 확대됨에없는이 기능이 필요한 경우처럼 해결할 수 이 :

map.values().remove(map.values().toArray()[index]); 

아마 아주 (특히 메모리 현명한) 효율적,하지만 당신이 될 것으로 기대 하듯이 O(N)을해야하지.


는, BTW 나는 질문은 모든 List 운영을위한 합법적이라고 생각합니다. (그것은 바로, 어쨌든보다 느린 LinkedList 안?) 나는 LinkedHashMap을 확장하고 List 인터페이스를 구현 LinkedHashMapList을 착수

. 놀랍게도 제거를위한 충돌로 인해 불가능한 것처럼 보입니다. 기존 remove 메서드는 이전에 매핑 된 개체를 반환하고 List.removeboolean을 반환합니다.

그것은 단지 반성입니다. 솔직히 말해서 LinkedHashMapLinkedList처럼 취급 될 수 없다는 것을 알게되었습니다. 당신이 성능 당신이 entries 배열을 캐시하지 않는 매우 가난한 될 가능성이 볼 수 있듯이

+0

예, 그것도 보았습니다 ... LinkedHashMap에 대한 remove() 메서드는 HashMap에서 오는 것으로 LinkedHashMap은 HashMap을 확장하므로 목록의 remove()와 충돌합니다 ... –

1

당신이 랜덤 액세스를 원하는 경우에 당신은

Map<K,V> map = new LinkedHashMap<K,V>(); 
Map.Entry<K,V>[] entries = (Map.Entry<K,V>[]) map.toArray(new Map.Entry[map.size()]); 
Map.Entry<K,V> entry_n = entry[n]; 

을 할 수 있습니다.

그러나 나는 그것에 대한 필요성을 질문 할 것입니다.

0

색인에 의한 액세스의 로그 (N) 효율로 맵을 작성하는 데 실제 문제는 없습니다. 빨강 - 검정 트리를 사용하고 각 노드에 대해 해당 노드에서 시작하는 트리의 요소 수를 저장하면 log (N) 인 get (int 인덱스) 메서드를 작성할 수 있습니다.

+0

이것은 질문에 대답하지 않는 것 같습니다. –

관련 문제