ฉันรู้เกี่ยวกับSortedSet
แต่ในกรณีของฉันฉันต้องการสิ่งที่นำไปปฏิบัติและไม่List
Set
ดังนั้นจึงมีการนำไปใช้งานใน API หรือที่อื่น ๆ หรือไม่?
ไม่น่าจะยากที่จะนำไปใช้เอง แต่ฉันคิดว่าทำไมไม่ถามคนที่นี่ก่อน
ฉันรู้เกี่ยวกับSortedSet
แต่ในกรณีของฉันฉันต้องการสิ่งที่นำไปปฏิบัติและไม่List
Set
ดังนั้นจึงมีการนำไปใช้งานใน API หรือที่อื่น ๆ หรือไม่?
ไม่น่าจะยากที่จะนำไปใช้เอง แต่ฉันคิดว่าทำไมไม่ถามคนที่นี่ก่อน
คำตอบ:
ไม่มีคอลเลกชัน Java ในไลบรารีมาตรฐานที่จะทำสิ่งนี้ LinkedHashSet<E>
เก็บรักษาคำสั่งเช่นเดียวกับ a List
ดังนั้นหากคุณห่อชุดของคุณในList
เวลาที่คุณต้องการใช้เป็นList
คุณจะได้รับความหมายที่คุณต้องการ
หรืออีกวิธีหนึ่งCommons Collections (หรือcommons-collections4
สำหรับรุ่นทั่วไป) มีList
สิ่งที่คุณต้องการอยู่แล้ว: SetUniqueList
/ SetUniqueList<E>
.
นี่คือสิ่งที่ฉันทำและได้ผล
สมมติว่าผมมีการทำงานกับสิ่งแรกที่ผมทำถูกสร้างขึ้นใหม่ArrayList
LinkedHashMap
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
จากนั้นฉันพยายามเพิ่มองค์ประกอบใหม่ของฉันในไฟล์LinkedHashSet
. วิธีการเพิ่มจะไม่แก้ไขLinkedHasSet
และส่งคืนเท็จหากองค์ประกอบใหม่ซ้ำกัน ดังนั้นนี่จึงกลายเป็นเงื่อนไขที่ฉันสามารถทดสอบได้ก่อนที่จะเพิ่มไฟล์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);
}
}
}
ทำไมไม่ห่อหุ้มชุดด้วยรายการเรียงลำดับดังนี้:
new ArrayList( new LinkedHashSet() )
สิ่งนี้ทำให้การนำไปใช้งานอื่น ๆ สำหรับผู้ที่เป็นผู้เชี่ยวชาญในคอลเล็กชันจริง
คุณควรพิจารณาคำตอบของ dhiller อย่างจริงจัง:
new ArrayList(set)
(หรือnew LinkedList(set)
อะไรก็ได้)ฉันคิดว่าวิธีแก้ปัญหาที่คุณโพสต์พร้อมกับNoDuplicatesList
ปัญหาบางอย่างส่วนใหญ่เป็นcontains()
วิธีการบวกกับชั้นเรียนของคุณไม่สามารถจัดการกับการตรวจสอบรายการที่ซ้ำกันในคอลเล็กชันที่ส่งไปยังaddAll()
วิธีการของคุณ
ฉันต้องการอะไรแบบนั้นดังนั้นฉันจึงไปที่คอลเลกชันคอมมอนส์และใช้SetUniqueList
แต่เมื่อฉันทำการทดสอบประสิทธิภาพฉันพบว่าดูเหมือนว่าจะไม่ได้รับการปรับให้เหมาะสมที่สุดเมื่อเทียบกับเคสถ้าฉันต้องการใช้ a Set
และรับArray
โดยใช้Set.toArray()
วิธีการ
SetUniqueTest
เอา20: 1 เวลาในการกรอกข้อมูลการสำรวจแล้ว100,000 Stringsเมื่อเทียบกับการดำเนินการอื่น ๆ ซึ่งเป็นความแตกต่างเรื่องใหญ่
ดังนั้นหากคุณกังวลเกี่ยวกับประสิทธิภาพฉันขอแนะนำให้คุณใช้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));
}
}
เอกสารสำหรับการเชื่อมต่อคอลเลกชันกล่าวว่า:
Set - คอลเล็กชันที่ไม่สามารถมีองค์ประกอบที่ซ้ำกันได้
รายการ - คอลเลกชันที่สั่งซื้อ (บางครั้งเรียกว่าลำดับ) รายการอาจมีองค์ประกอบที่ซ้ำกัน
ดังนั้นหากคุณไม่ต้องการซ้ำกันคุณอาจไม่ควรใช้รายการ
ในadd
วิธีการทำไมไม่ใช้HashSet.add()
เพื่อตรวจสอบรายการที่ซ้ำกันแทนที่จะเป็นHashSet.consist()
.
HashSet.add()
จะกลับมาtrue
หากไม่มีการทำซ้ำหรือfalse
อย่างอื่น
HashSet#consist()
?
จากด้านบนของหัวของฉันรายการอนุญาตให้ทำซ้ำ คุณสามารถใช้งานUniqueArrayList
และแทนที่ฟังก์ชันadd
/ ทั้งหมดinsert
เพื่อตรวจสอบได้อย่างรวดเร็วcontains()
ก่อนที่คุณจะเรียกใช้วิธีการที่สืบทอด สำหรับการใช้งานส่วนตัวคุณสามารถใช้add
วิธีการที่คุณใช้เท่านั้นและแทนที่วิธีอื่น ๆ เพื่อให้เกิดข้อยกเว้นในกรณีที่โปรแกรมเมอร์ในอนาคตพยายามใช้รายการในลักษณะอื่น
ฉันเพิ่งสร้าง UniqueList ของตัวเองในห้องสมุดเล็ก ๆ ของฉันเองดังนี้:
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 ที่สามารถส่งคืนได้เช่นเดียวกับอาร์เรย์วัตถุ