[java] List를 구현하는 Set을 보존하는 게재 신청서가 있습니까?

나는의 구현을 찾기 위해 노력하고있어 java.util.Listjava.util.Set자바에서 동시에합니다. 이 클래스는 고유 한 요소 ( Set) 만 허용 하고 순서 (예 :)를 유지하기 를 원합니다 List. JDK 6에 존재합니까?

List<T>#add(int, T)특정 위치에 삽입 할 수 있도록하는 것이 중요합니다 .



답변

TreeSet요소 순서로 정렬됩니다. LinkedHashSet게재 신청서를 유지합니다. 그 중 하나가 당신이 추구했던 것입니다.

당신은 당신이에 삽입 할 수하도록 지정한 임의의 위치, 당신이 당신의 자신의 작성해야 의심 – 단지 포함하는 클래스 생성 HashSet<T>과를 ArrayList<T>; 항목을 추가 할 때 목록에 추가하기 전에 세트에 있는지 여부를 확인하십시오.

또한 아파치의 평민 – collections4 제공 ListOrderedSetSetUniqueList유사하게 동작 주어진 요구 사항을 충족해야합니다.


답변

LinkedHashSet이 답입니다.

반복 순서 및 고유성.

http://download.oracle.com/javase/6/docs/api/java/util/LinkedHashSet.html


답변

당신은 같은 의미 LinkedHashSet입니까? 이렇게하면 항목 순서가 유지되지만 중복은 허용되지 않습니다.

IMHO는 특이한 요구 사항이지만 중복없이 목록을 작성할 수 있습니다.

class SetList<T> extends ArrayList<T> {
    @Override
    public boolean add(T t) {
        return !super.contains(t) && super.add(t);
    }

    @Override
    public void add(int index, T element) {
        if (!super.contains(element)) super.add(index, element);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            added |= add(t);
        return added;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            if (!super.contains(t)) {
                super.add(index++, t);
                added = true;
            }
        return added;
    }
}


답변

당신은 구현할 수 없습니다 ListSet계약 위반하지 않고 한 번에. 예를 들어 Set.hashCode계약 을 참조하십시오 .

집합의 해시 코드는 집합에있는 요소의 해시 코드의 합으로 정의되며, 여기서 null 요소의 해시 코드는 0으로 정의됩니다.

반면에 계약은 List.hashCode다음 과 같습니다.

목록의 해시 코드는 다음 계산의 결과로 정의됩니다.

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

따라서 두 계약이 모두 이행되도록 보장하는 단일 클래스를 구현하는 것은 불가능합니다. equals구현 에도 동일한 문제가 있습니다.


답변

JDK 6으로 제한하지 않으 려면 필요에 정확히 일치하는 Apache 공통 컬렉션 라이브러리 인 ListOrderedSet을 사용할 수 있습니다. 그것은 같은거야 ListSet함께 결합 🙂


답변

비슷한 문제가있어서 직접 작성했습니다. 를 참조하십시오 여기 . 는 IndexedArraySet확장 ArrayList및 구현 Set하므로 필요한 모든 작업을 지원해야합니다. ArrayList다음 요소를 모두 이동해야하므로 큰 목록 의 경우 중간 위치에 요소를 삽입 하면 속도가 느려질 수 있습니다. 나는 IndexedArraySet그것을 바꾸지 않는다.


답변

다른 옵션 ( List인터페이스 요구 사항 제외)은 Guava의 ImmutableSet이며 삽입 순서를 유지합니다. 에서 자신의 위키 페이지 :

정렬 된 컬렉션을 제외하고 는 구성 시간부터 순서가 유지됩니다. 예를 들면

ImmutableSet.of("a", "b", "c", "a", "d", "b")

“a”, “b”, “c”, “d”순서로 요소를 반복합니다.