2012-08-16 4 views
1

게재 순위 콜렉션을 찾고 위치의 효율적인 조회 및 하위 세트보기 (예 : 하위 목록)를 허용합니다. 이것에 대한 가장 간단한 옵션은 List의 linked list 접근법을 취하고 노드를 맵 값으로 포함하고 클래스의 목록 인터페이스의 일부 또는 전체를 노출하는 것입니다. 누군가가 이것에 대해 오라클에 나쁜 것인가Java ListSet 어딘가에?

? 정렬 된지도 및 세트에 NavigableMap/Set가 추가되어 훨씬 더 일반적인 게재 신청서가없는 경우 ...

편집 : 제발 LinkedHashSet을 제안하지 마십시오. 위치를 쿼리하거나 할 수있는 방법이 없습니다. 상대적 부분 집합.

+2

왜 직접 구현하지 않습니까? 이것은 반드시 구현해야하는 단순한 데이터 구조는 아님을 발견하십시오. (나열된 제약 조건으로 인해 O (n) 시간보다 더 나은 위치 쿼리를 지원하는 것이 꽤 어렵습니다.이 작업은'LinkedHashSet'을 감싸는 래퍼로 구현할 수 있습니다.) 어떤 경우에도, _이 구조에서 일부 라이브러리는 실제로 API에이 라이브러리를 추가하는 데 관심이 있습니다. –

+0

그 이유는 간단합니다. 대부분의 시간을 소비하는 컬렉션은 요소의 일부에 대한 멤버십을 반복 및 쿼리 할 때 랜덤 액세스가 필요하며 인덱스가 필요합니다. 따라서지도 또는 집합 중 하나입니다. 웃음은 '그것의 부분'입니다. 리스트가 이것에 대한 탁월한 단일 메소드 (하위리스트, 콜렉션 프레임 워크에서 가장 영감을받은 메소드라고 생각하는)가있는 곳에서는 * 일부 * maps/sets만이 jdk에서 허용되며 악몽 같은 Navigable/Set/Map을 구현하면됩니다. 어쨌든 정렬 된 컬렉션만을위한 것입니다 - 어떤 Linked variant에 대해 subSet/Map (index, index)을 만들 수있을 때 getIndex를 추가 할 때 – i30817

+0

getindex가 너무 비싸면 (일부 구현에서는 노드에 int를 유지해야합니까?), 객체를 키 (set-implemented-as-map)로 직접 사용하고 링크 된 하위 구조로 '하위 집합'을 만듭니다. linkedhashset.subSet (V low, V high). 아마도지도가 쉽지 않을 것입니다. – i30817

답변

2

당신은 java.util.LinkedHashSet 같은 의미 : 예측 가능한 반복 순서를 가지는

해시 테이블과 Set 인터페이스의 링크리스트의 구현을. 이 구현은 모든 항목을 통해 실행되는 이중 연결 목록을 유지한다는 점에서 HashSet 과 다릅니다. 이 링크 된 목록은 요소가 집합 (삽입 순서)에 삽입 된 순서 인 반복 순서를 정의합니다. 요소를 에 다시 삽입하면 삽입 순서가 영향을받지 않습니다. (. s.add 경우는 요소 e가 세트의 재 삽입한다 (e)는 s.contains (e)는 직전 호출로 true를 반환 할 때 가 호출)

+0

아니요 linkedhashset은 객체의 위치를 ​​쿼리하거나 객체의 'before'또는 'after'에 기반하여 하위 세트를 생성하기 위해 public 인터페이스 (또는 해시 세트를 확장하므로 private)가 없기 때문에 특별히 linkedhashset과 같은 의미는 아닙니다. – i30817

+1

@ i30817 그래서, 기본적으로 몇 가지 추가 작업이있는 연결된 해시 집합을 의미합니까? 다음은 ASF 라이센스 구현입니다. http://svn.apache.org/repos/asf/harmony/enhanced/java/trunk/classlib/modules/luni/src/main/java/java/util/LinkedHashSet.java 자유롭게 사용해보십시오. 그것을 강화하십시오. – Marcin

0

EDIT2 : 새로운 최종 버전 다음은 약간 조정 된 함수 (2로 나뉘며 더 이상지도의 시작으로 null을 허용하지 않음)가있는 집합에 대한 버전입니다.

public class LinkedSet<E> implements Set<E> { 

private LinkedHashMap<E, Integer> m = new LinkedHashMap<E, Integer>(); 
private int monoticallyIncreasing; 

/** 
* Returns true if the value target was added before (exclusive) 
* limitElem in insertion order. 
* 
* If target or limit are not present on the set this method returns false 
* 
* @param limitElem a E that may be a element of the set or not. 
* @return if target was added before limit (can be reset by removing and 
* re-adding the target, that changes iteration order). 
*/ 
public boolean containsBefore(E target, E limitElem) { 
    if (isEmpty()) { 
     return false; 
    } 

    Integer targetN = m.get(target); 
    if (targetN == null) { 
     return false; 
    } 

    Integer highN = m.get(limitElem); 
    if (highN == null) { 
     return false; 
    } 
    return targetN < highN; 
} 

/** 
* Returns true if the value target was added after (exclusive) 
* previousElem in insertion order. 
* 
* If target or previous are not present on the set this method returns false 
* 
* @param previousElem a E that may be a element of the set or not. 
* @return if target was added before previous (can be reset by removing and 
* re-adding the target, that changes iteration order). 
*/ 
public boolean containsAfter(E target, E previousElem) { 
    if (isEmpty()) { 
     return false; 
    } 

    Integer targetN = m.get(target); 
    if (targetN == null) { 
     return false; 
    } 

    Integer low = m.get(previousElem); 
    if (low == null) { 
     return false; 
    } 
    return low < targetN; 
} 

@Override 
public boolean add(E e) { 
    Integer pos = m.get(e); 
    if (pos == null) { 
     m.put(e, monoticallyIncreasing++); 
     return true; 
    } 
    return false; 
} 

@Override 
public int size() { 
    return m.size(); 
} 

@Override 
public boolean isEmpty() { 
    return m.isEmpty(); 
} 

@Override 
public boolean contains(Object o) { 
    return m.containsKey(o); 
} 

@Override 
public Object[] toArray() { 
    Object[] result = new Object[size()]; 
    int i = 0; 
    for (E e : this) { 
     result[i++] = e; 
    } 
    return result; 
} 

@Override 
@SuppressWarnings("unchecked") 
public <T> T[] toArray(T[] a) { 
    int size = size(); 
    if (a.length < size) { 
     a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); 
    } 
    int i = 0; 
    Object[] result = a; 
    for (E e : this) { 
     result[i++] = e; 
    } 
    if (a.length > size) { 
     //peculiar toArray contract where it doesn't care about the rest 
     a[size] = null; 
    } 
    return a; 
} 

@Override 
public boolean remove(Object o) { 
    return m.remove(o) != null; 
} 

@Override 
public boolean addAll(Collection<? extends E> c) { 
    boolean changed = false; 
    for (E e : c) { 
     changed |= add(e); 
    } 
    return changed; 
} 

@Override 
public boolean containsAll(Collection<?> c) { 
    return m.keySet().containsAll(c); 
} 

@Override 
public boolean retainAll(Collection<?> c) { 
    return m.keySet().retainAll(c); 
} 

@Override 
public boolean removeAll(Collection<?> c) { 
    return m.keySet().removeAll(c); 
} 

@Override 
public void clear() { 
    m.clear(); 
} 

@Override 
public Iterator<E> iterator() { 
    return m.keySet().iterator(); 
} 
} 
+0

humm - 유용하지만,()/descendingFrom()에서 iterator를 사용하고 싶습니다. 그러나 LinkedHashMap은 노드 목록이나 노드에 액세스 할 수 없습니다. 그것이 이전 버전으로 돌아간 것 같아요. – i30817

+0

이 [코멘트] (http://stackoverflow.com/a/12023209/214260)에 그 구현을 보여줍니다. – i30817