무도한 목록 구현이 있습니까?
-
06-07-2019 - |
문제
나는 알고있다 SortedSet
,하지만 내 경우에는 구현하는 것이 필요합니다 List
, 그렇지 않습니다 Set
. API 또는 다른 곳에서 구현이 있습니까?
나 자신을 구현하는 것은 어렵지 않아야하지만, 왜 사람들에게 먼저 물어 보지 않겠습니까?
해결책
표준 라이브러리에는이를 수행 할 Java 컬렉션이 없습니다. LinkedHashSet<E>
a와 유사하게 주문을 보존합니다 List
, 하지만 세트를 감싸면 List
당신이 그것을 사용하고 싶을 때 List
당신은 당신이 원하는 의미를 얻을 것입니다.
대안 적으로, 커먼즈 컬렉션 (또는 commons-collections4
, 일반 버전의 경우) a List
이미 원하는 것을 수행합니다. SetUniqueList
/ SetUniqueList<E>
.
다른 팁
여기에 내가 한 일과 그것이 작동합니다.
내가 있다고 가정합니다 ArrayList
내가 한 첫 번째 일과 함께 일하는 것은 새로운 것을 만들었습니다. LinkedHashMap
.
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
그런 다음 새 요소를 LinkedHashSet
. ADD 메소드는 변경되지 않습니다 LinkedHasSet
새 요소가 복제 인 경우 False를 반환합니다. 그래서 이것은 추가하기 전에 테스트 할 수있는 조건이됩니다. ArrayList
.
if (hashSet.add(E)) arrayList.add(E);
이것은 중복이 배열 목록에 추가되는 것을 방지하는 간단하고 우아한 방법입니다. 원한다면 캡슐화하고 클래스에서 ADD 메소드를 재정의 할 수 있습니다. ArrayList
. 다루는 것을 잊지 마십시오 addAll
요소를 반복하고 추가 방법을 호출함으로써.
그래서 여기 내가 결국 한 일이 있습니다. 나는 이것이 다른 사람을 돕기를 바랍니다.
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);
}
}
}
Dhiller의 대답을 진지하게 고려해야합니다.
- 객체를 중복없는 목록에 추가하는 것에 대해 걱정하는 대신 세트 (모든 구현)에 추가하여 중복을 필터링합니다.
- 목록이 필요한 메소드를 호출 해야하는 경우
new ArrayList(set)
(또는 anew LinkedList(set)
, 무엇이든).
나는 당신이 게시 한 솔루션이라고 생각합니다 NoDuplicatesList
주로 몇 가지 문제가 있습니다 contains()
메소드, 플러스 클래스는 귀하에게 전달 된 컬렉션의 중복 확인을 처리하지 않습니다. addAll()
방법.
목록이있는 세트를 캡슐화하지 않겠습니까?
new ArrayList( new LinkedHashSet() )
이것은 실제 컬렉션 마스터 인 사람을위한 다른 구현을 남깁니다. ;-)
나는 그런 무언가가 필요했기 때문에 Commons 컬렉션에 가서 Setuniquelist를 사용했지만 성능 테스트를 실행했을 때 세트를 사용하고 배열을 사용하여 배열을 얻으려면 케이스와 비교하여 최적화되지 않은 것으로 나타났습니다. set.toArray () 메소드, setuniqueTest는 다른 구현과 비교하여 100,000 문자열을 채우는 데 20 : 1 시간이 걸렸으며, 이는 큰 차이가되므로 성능에 대해 걱정하면 세트를 사용하는 것이 좋습니다. 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에 감사합니다http://abusleem.net/blog
참고 : 걸리지 않습니다 서브리스트 고려한 구현.
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));
}
}
그만큼 수집 인터페이스에 대한 문서 말 :
세트 - 중복 요소를 포함 할 수없는 컬렉션.
목록 - 순서 컬렉션 (때로는 시퀀스라고 함). 목록에는 중복 요소가 포함될 수 있습니다.
따라서 복제를 원하지 않으면 목록을 사용해서는 안됩니다.
안에 add
방법, 사용하지 않는 이유 HashSet.add()
대신 복제를 확인합니다 HashSet.consist()
.
HashSet.add()
돌아올 것입니다 true
중복이없는 경우 false
그렇지 않으면.
내 머리 꼭대기에서 목록은 복제를 허용합니다. 빠르게 구현할 수 있습니다 UniqueArrayList
그리고 모든 것을 무시합니다 add
/ insert
확인할 기능 contains()
상속 된 방법을 호출하기 전에. 개인적으로 사용하기 위해서만 구현할 수 있습니다 add
미래의 프로그래머가 다른 방식으로 목록을 사용하려고 할 경우를 대비하여 사용하는 방법을 사용하여 다른 사람을 무시하고 다른 사람을 대체합니다.
나는 방금 내 자신의 작은 도서관에서 내 자신의 독창적 인 것을 이렇게 만들었다.
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);
}
}
잘 작동합니다. 아직 세트에 추가 된 경우, 이미없고 객체 배열뿐만 아니라 반환 가능한 배열리스트가있는 경우 세트에 추가됩니다.