나는 알고 SortedSet
있지만, 내 경우에는 그 구현 뭔가가 필요 List
, 그리고 Set
. 그렇다면 API 또는 다른 곳에 구현이 있습니까?
나 자신을 구현하는 것은 어렵지 않지만, 여기 사람들에게 먼저 물어 보는 것은 어떨까?
나는 알고 SortedSet
있지만, 내 경우에는 그 구현 뭔가가 필요 List
, 그리고 Set
. 그렇다면 API 또는 다른 곳에 구현이 있습니까?
나 자신을 구현하는 것은 어렵지 않지만, 여기 사람들에게 먼저 물어 보는 것은 어떨까?
답변:
이 작업을 수행하는 표준 라이브러리에는 Java 컬렉션이 없습니다. LinkedHashSet<E>
List
그래도 a와 유사하게 순서를 유지 하므로 a List
로 사용하고 싶을 때 세트를 a로 래핑 하면 원하는 List
의미를 얻을 수 있습니다.
또는 Commons Collections (또는 commons-collections4
일반 버전의 경우)에는 List
이미 원하는 작업을 수행하는 SetUniqueList
/ SetUniqueList<E>
.
여기 내가 한 일이 있으며 작동합니다.
내가이 있으리라 믿고 ArrayList
내가 한 첫 번째 일은 함께 작동하도록하는 것은 새를 만들었습니다 LinkedHashMap
.
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
그런 다음 새 요소를 LinkedHashSet
. add 메서드는를 변경하지 않고 LinkedHasSet
새 요소가 중복 된 경우 false를 반환합니다. 그래서 이것은 ArrayList
.
if (hashSet.add(E)) arrayList.add(E);
이것은 중복 항목이 배열 목록에 추가되는 것을 방지하는 간단하고 우아한 방법입니다. 원하는 경우 .NET Framework를 확장하는 클래스에서이를 캡슐화하고 add 메서드를 재정의 할 수 있습니다 ArrayList
. addAll
요소를 반복하고 add 메서드를 호출하여 처리하는 것을 잊지 마십시오.
그래서 결국 제가 한 일이 있습니다. 다른 사람에게 도움이되기를 바랍니다.
class NoDuplicatesList<E> extends LinkedList<E> {
@Override
public boolean add(E e) {
if (this.contains(e)) {
return false;
}
else {
return super.add(e);
}
}
@Override
public boolean addAll(Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(copy);
}
@Override
public boolean addAll(int index, Collection<? extends E> collection) {
Collection<E> copy = new LinkedList<E>(collection);
copy.removeAll(this);
return super.addAll(index, copy);
}
@Override
public void add(int index, E element) {
if (this.contains(element)) {
return;
}
else {
super.add(index, element);
}
}
}
목록으로 집합을 캡슐화하지 않는 이유는 다음과 같습니다.
new ArrayList( new LinkedHashSet() )
이것은 Collections의 진정한 마스터 인 누군가를 위해 다른 구현을 남겨 둡니다 ;-)
dhiller의 대답을 진지하게 고려해야합니다.
new ArrayList(set)
(또는 a new LinkedList(set)
등)로 래핑합니다 .귀하가 게시 한 솔루션 NoDuplicatesList
에는 주로 contains()
메서드에 문제가 있으며 클래스가 addAll()
메서드에 전달 된 Collection의 중복 검사를 처리하지 않는다고 생각합니다 .
나는 갔다, 그래서 나는 그런 일을 필요 평민 컬렉션 과를 사용 SetUniqueList
하지만 일부 성능 테스트를 실행했을 때, 나는 그것이 내가 사용하려는 경우 경우에 비교 최적화되지 않은 것 같습니다 것을 발견 Set
하고 얻을 Array
사용 Set.toArray()
방법을.
다른 구현에 비해 100,000 개의 문자열 을 채운 다음 순회 하는 SetUniqueTest
데 20 : 1의 시간 이 걸렸 는데 이는 큰 차이입니다.
따라서 성능이 걱정된다면를 사용하는 대신 Set and Get an Array 를 사용하는 것이 좋습니다 . SetUniqueList
,의 논리가 실제로 필요하지 않으면 SetUniqueList
다른 솔루션을 확인해야합니다.
테스트 코드 주요 방법 :
public static void main(String[] args) {
SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();
long t1 = 0L;
long t2 = 0L;
String t;
t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;
t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
s.add("a" + Math.random());
}
s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
t = d[i];
}
t2 = System.nanoTime() - t2;
System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2); //comparing results
}
감사합니다, Mohammed Sleem
참고 : 하위 목록 구현은 고려 하지 않습니다 .
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class UniqueList<T> extends ArrayList<T> {
private static final long serialVersionUID = 1L;
/** Unique elements SET */
private final Set<T> set=new HashSet();
/** Used by addAll methods */
private Collection<T> addUnique(Collection<? extends T> col) {
Collection<T> unique=new ArrayList();
for(T e: col){
if (set.add(e)) unique.add(e);
}
return unique;
}
@Override
public boolean add(T e) {
return set.add(e) ? super.add(e) : false;
}
@Override
public boolean addAll(Collection<? extends T> col) {
return super.addAll(addUnique(col));
}
@Override
public void add(int index, T e) {
if (set.add(e)) super.add(index, e);
}
@Override
public boolean addAll(int index, Collection<? extends T> col) {
return super.addAll(index, addUnique(col));
}
}
컬렉션 인터페이스에 대한 문서는 말합니다 :
집합 — 중복 요소를 포함 할 수없는 모음입니다.
목록 — 정렬 된 컬렉션 (시퀀스라고도 함). 목록에는 중복 요소가 포함될 수 있습니다.
따라서 중복을 원하지 않는 경우 목록을 사용하지 않아야합니다.
내 머리 꼭대기에서 목록은 중복을 허용합니다. 상속 된 메서드를 호출하기 전에를 빠르게 구현하고 UniqueArrayList
모든 add
/ insert
함수를 재정 의하여 확인할 contains()
수 있습니다. 개인적인 용도로 사용하는 경우에만 add
사용 하는 방법을 구현하고 미래의 프로그래머가 다른 방식으로 목록을 사용하려고 할 경우 예외를 throw하도록 다른 방법을 재정의 할 수 있습니다.
나는 다음과 같이 내 자신의 작은 라이브러리에서 내 고유 목록을 만들었습니다.
package com.bprog.collections;//my own little set of useful utilities and classes
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jonathan
*/
public class UniqueList {
private HashSet masterSet = new HashSet();
private ArrayList growableUniques;
private Object[] returnable;
public UniqueList() {
growableUniques = new ArrayList();
}
public UniqueList(int size) {
growableUniques = new ArrayList(size);
}
public void add(Object thing) {
if (!masterSet.contains(thing)) {
masterSet.add(thing);
growableUniques.add(thing);
}
}
/**
* Casts to an ArrayList of unique values
* @return
*/
public List getList(){
return growableUniques;
}
public Object get(int index) {
return growableUniques.get(index);
}
public Object[] toObjectArray() {
int size = growableUniques.size();
returnable = new Object[size];
for (int i = 0; i < size; i++) {
returnable[i] = growableUniques.get(i);
}
return returnable;
}
}
다음과 같은 TestCollections 클래스가 있습니다.
package com.bprog.collections;
import com.bprog.out.Out;
/**
*
* @author Jonathan
*/
public class TestCollections {
public static void main(String[] args){
UniqueList ul = new UniqueList();
ul.add("Test");
ul.add("Test");
ul.add("Not a copy");
ul.add("Test");
//should only contain two things
Object[] content = ul.toObjectArray();
Out.pl("Array Content",content);
}
}
잘 작동합니다. 그것이하는 일은 집합에 아직 추가하지 않고 반환 가능한 Arraylist와 객체 배열이있는 경우 추가하는 것입니다.