Saya tahu tentang SortedSet
, tetapi dalam kasus saya, saya membutuhkan sesuatu yang mengimplementasikan List
, dan tidak Set
. Jadi apakah ada implementasi di luar sana, di API atau di tempat lain?
Seharusnya tidak sulit untuk menerapkan diri saya sendiri, tetapi saya pikir mengapa tidak bertanya kepada orang-orang di sini dulu?
java
list
collections
duplicates
Yuval
sumber
sumber
Jawaban:
Tidak ada koleksi Java di pustaka standar untuk melakukan ini.
LinkedHashSet<E>
mempertahankan pengurutan mirip dengan aList
, jadi jika Anda membungkus set Anda diList
saat Anda ingin menggunakannya sebagai,List
Anda akan mendapatkan semantik yang Anda inginkan.Atau, Koleksi Commons (atau
commons-collections4
, untuk versi generik) memilikiList
mana yang sudah melakukan apa yang Anda inginkan:SetUniqueList
/SetUniqueList<E>
.sumber
Inilah yang saya lakukan dan berhasil.
Dengan asumsi saya harus
ArrayList
bekerja dengan hal pertama yang saya lakukan adalah membuat yang baruLinkedHashMap
.LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
Kemudian saya mencoba menambahkan elemen baru saya ke
LinkedHashSet
. Metode add tidak mengubahLinkedHasSet
dan mengembalikan false jika elemen baru adalah duplikat. Jadi ini menjadi kondisi yang bisa saya uji sebelum menambahkanArrayList
.if (hashSet.add(E)) arrayList.add(E);
Ini adalah cara sederhana dan elegan untuk mencegah duplikat ditambahkan ke daftar array. Jika mau, Anda bisa merangkumnya dan mengganti metode add dalam kelas yang memperluas ekstensi
ArrayList
. Ingatlah untuk menangani denganaddAll
mengulang melalui elemen dan memanggil metode add.sumber
Jadi, inilah yang akhirnya saya lakukan. Saya harap ini membantu orang lain.
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); } } }
sumber
Mengapa tidak merangkum satu set dengan daftar, urutkan seperti:
new ArrayList( new LinkedHashSet() )
Ini meninggalkan implementasi lain untuk seseorang yang merupakan master Koleksi yang sebenarnya ;-)
sumber
Anda harus secara serius mempertimbangkan jawaban dhiller:
new ArrayList(set)
(atau anew LinkedList(set)
, apa saja).Saya pikir solusi yang Anda posting dengan
NoDuplicatesList
memiliki beberapa masalah, sebagian besar dengancontains()
metode, ditambah kelas Anda tidak menangani pemeriksaan duplikat dalam Collection yang diteruskan keaddAll()
metode Anda .sumber
Saya membutuhkan sesuatu seperti itu, jadi saya pergi ke koleksi commons dan menggunakan
SetUniqueList
, tetapi ketika saya menjalankan beberapa tes kinerja, saya menemukan bahwa tampaknya tidak dioptimalkan dibandingkan dengan kasus jika saya ingin menggunakanSet
dan mendapatkanArray
menggunakanSet.toArray()
metode tersebut.Diperlukan
SetUniqueTest
waktu 20: 1 untuk mengisi dan kemudian melintasi 100.000 String dibandingkan dengan implementasi lainnya, yang merupakan perbedaan besar.Jadi, jika Anda khawatir tentang kinerjanya, saya sarankan Anda untuk menggunakan Set dan Dapatkan Array daripada menggunakan
SetUniqueList
, kecuali jika Anda benar-benar membutuhkan logikaSetUniqueList
, maka Anda harus memeriksa solusi lain ...Menguji metode utama kode :
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
}
Hormat kami, Mohammed Sleem
sumber
CATATAN: ini tidak memperhitungkan implementasi subList .
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)); } }
sumber
The dokumentasi untuk antarmuka koleksi mengatakan:
Jadi, jika Anda tidak ingin duplikat, Anda mungkin tidak boleh menggunakan daftar.
sumber
Dalam
add
metode, mengapa tidak menggunakanHashSet.add()
untuk memeriksa duplikat, bukanHashSet.consist()
.HashSet.add()
akan kembalitrue
jika tidak ada duplikat danfalse
sebaliknya.sumber
HashSet#consist()
?Di luar kepala saya, daftar memungkinkan duplikat. Anda dapat dengan cepat mengimplementasikan
UniqueArrayList
dan mengganti semuaadd
/insert
functions yang akan diperiksacontains()
sebelum Anda memanggil metode yang diwariskan. Untuk penggunaan pribadi, Anda hanya dapat mengimplementasikanadd
metode yang Anda gunakan, dan menimpa yang lain untuk memberikan pengecualian jika programmer masa depan mencoba menggunakan daftar dengan cara yang berbeda.sumber
Saya baru saja membuat UniqueList saya sendiri di perpustakaan kecil saya sendiri seperti ini:
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; } }
Saya memiliki kelas TestCollections yang terlihat seperti ini:
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); } }
Bekerja dengan baik. Yang dilakukannya hanyalah menambahkan ke set jika belum memilikinya dan ada Arraylist yang dapat dikembalikan, serta array objek.
sumber