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();
}
}
왜 직접 구현하지 않습니까? 이것은 반드시 구현해야하는 단순한 데이터 구조는 아님을 발견하십시오. (나열된 제약 조건으로 인해 O (n) 시간보다 더 나은 위치 쿼리를 지원하는 것이 꽤 어렵습니다.이 작업은'LinkedHashSet'을 감싸는 래퍼로 구현할 수 있습니다.) 어떤 경우에도, _이 구조에서 일부 라이브러리는 실제로 API에이 라이브러리를 추가하는 데 관심이 있습니다. –
그 이유는 간단합니다. 대부분의 시간을 소비하는 컬렉션은 요소의 일부에 대한 멤버십을 반복 및 쿼리 할 때 랜덤 액세스가 필요하며 인덱스가 필요합니다. 따라서지도 또는 집합 중 하나입니다. 웃음은 '그것의 부분'입니다. 리스트가 이것에 대한 탁월한 단일 메소드 (하위리스트, 콜렉션 프레임 워크에서 가장 영감을받은 메소드라고 생각하는)가있는 곳에서는 * 일부 * maps/sets만이 jdk에서 허용되며 악몽 같은 Navigable/Set/Map을 구현하면됩니다. 어쨌든 정렬 된 컬렉션만을위한 것입니다 - 어떤 Linked variant에 대해 subSet/Map (index, index)을 만들 수있을 때 getIndex를 추가 할 때 – i30817
getindex가 너무 비싸면 (일부 구현에서는 노드에 int를 유지해야합니까?), 객체를 키 (set-implemented-as-map)로 직접 사용하고 링크 된 하위 구조로 '하위 집합'을 만듭니다. linkedhashset.subSet (V low, V high). 아마도지도가 쉽지 않을 것입니다. – i30817