2013-12-20 4 views
2

맞춤형 비교기를 사용하여 세트를 메모리에 복제하지 않고 주문해야합니다.JAVA에서 중복되지 않은 세트 주문

순진 구현은 다음과 같습니다

Set<MyClass> newSet = new TreeSet<>(myComparator); 
newSet.addAll(oldSet); 

하지만이 경우에도 제한된 시간 동안, 나는 메모리에 두 세트를해야합니다, 그 의미합니다 : (정렬되지 않은) oldSet 및 newSet을 (주문). 그들은 매우 커질 것이므로 이것을 피하고 싶습니다.

나는 이런 식으로 뭔가를 수행하고 싶습니다 : 같은 구조 TreeSet에 대한 생성자가 없기 때문에 실제로 가능하지 않다

oldSet = new TreeSet<>(oldSet, myComparator); 

합니다.

해결책 일 수 있습니까?

Iterator<MyClass> it = oldSet.iterator(); 
Set<MyClass> newSet = new TreeSet<>(myComparator); 
while(it.hasNext()) 
{ 
    newSet.add(it.next()); 
    it.remove(); 
}  

뭔가 더 좋습니다.

당신이

+0

@kai'it.remove()'가 없으면 OP는 한 번에 두 개의 풀 세트를 메모리에 가지고 있는데, 이것은 그의 질문에 관한 것입니다. –

답변

0

Set이 정의에 의해 정렬되지 않기 때문에 감사 (당신이 그것을처럼) 당신이 정렬 된 데이터 구조를 사용해야하므로 Set을 주문하는 방법은 없습니다. 그러나 당신은 전혀 볼 문제에 대해 신경 쓸 필요가 없습니다. addAll을 수행하면 Java는 Set의 전체 복사본을 수행하지 않고 거의 RAM을 사용하지 않는 참조 만 복사합니다.

귀하의 addAll 솔루션은 깨끗하고 정확한 것입니다.

+0

"'Set '은 정의에 의해 정렬되지 않으므로'Set'을 정렬 할 방법이 없습니다."No ", Java에서 Set은 다르게 지정하지 않는 한 순서가 없습니다. 'SortedSet' (그 중,'TreeSet'가 구현 인)의 계약은, 아이템이 잘 정의 된 순서를 가지는 것을 보증합니다. – Smallhacker

+0

@Smallhacker 나는 세트에 대해 말하고 있었다. 세트가 없다면, 마침표가 없다. TreeSet은이 동작을 변경하는 특수한 Set입니다. – LionC

+0

아, 그래서 "Set _that is not ordered__를 주문할 수있는 방법이 없습니다." 좋아, 나쁘다. – Smallhacker

0

당신은 오래된 세트에 모든 참조를 null로 할 수있는 경우는 그것을 할

newSet.addAll(oldSet); 
oldSet = null; 

당신이 할 수있는 null가 아닌 기존 세트 사용 Set.clear 방법에 대한 모든 참조

newSet.addAll(oldSet); 
oldSet.clear(); 

참고하면 이후에 그 clear HashSet의 내부 해시 테이블이 축소되지 않습니다.

+0

해시 테이블은 유지되지만 모든 Map.Entry는 사라집니다. –

2

TreeSet을 사용하면 메모리 효율이 가장 떨어지며 가장 빠른 방법은 아닙니다.

당신은 ArrayList를 사용하고에 일종의 수행해야합니다

List<MyClass> sorted = new ArrayList<>(oldSet.size()); 
oldSet = null; 
Collections.sort(sorted, myComparator); 

ArrayList 내부에 사용되는 단일 배열의 오버 헤드가 문제가되지해야한다, 그리고 어떤 경우에 당신이 가질 수있는 가장 작은 문제입니다 .

일괄 대량 정렬 작업은 TreeSet의 각 개별 항목에 적합한 위치를 찾는 것보다 빠르며이 경우 필요한 모든 할당과 함께합니다.

+0

글쎄, 벌크 Collection.sort (mergesort)와 TreeSet 삽입 (n 로그에 각각 n 개 삽입)에 대해'n log n'을 기대할 것입니다. –

+0

@guido 이것은 추상적인 복잡성이 아니라 상수입니다. –

+0

메모리에 배열을 정렬하기위한 상수 요인에 대한 우려가 커지면 인프라를 점검해야합니다. :) 단지 chitchatting 일뿐입니다. 실제로 같은 대답을 제안했을 것입니다. 내 +1 –

0

집합에서 생성자를 사용하여 집합을 만들면 제비 복사본을 만듭니다. 참조 만 복사합니다. 삭제할 때도 참조를 삭제할 수 있습니다. 또한 아래의 코드에서 볼 :

MyComparator myComparator = new MyComparator(); 
Set<Object> newSet = new TreeSet<>(myComparator); 
Object mc = new Object(); 
newSet.add(mc); //set is created 

Set<Object> newerSet = new TreeSet<>(myComparator); 
newerSet.addAll(newSet); 
System.out.println(newSet); 
System.out.println(newerSet); 

출력 : [[email protected]] [있는 java.lang.Object @ 1bb1deea]

같은 개체에 대한 참조.

newerSet.remove(mc); 
System.out.println("After deletion"); 
System.out.println(newSet); 
System.out.println(newerSet); 

은 삭제 후 [[email protected]] []

만 참조가 제거된다.

0

next()을 호출 할 때마다 다음 정렬 된 항목을 제공하는 Iterator 구현을 작성해야합니다. 추가 메모리는 필요 없지만 순서가 지정되지 않은 Set을 복제하는 것보다 추가 메모리가 적습니다. 새로운 Set도 없지만 반복 할 수 있습니다.

메모리가 부족하지만 비효율적 인 알고리즘은 가장 최근에 액세스 한 항목을 Iterator에 저장합니다. 다음 항목을 반환해야 할 때마다 뒷면의 Set에있는 모든 항목을 검토하여 다음 항목을 파악합니다.