Существует ли дублирующая реализация списка?
Я знаю о SortedSet
, но в моем случае мне нужно что-то, что реализует List
, а не Set
. Так есть ли реализация там, в API или где-то еще?
Нельзя было бы реализовать себя, но я решил, почему сначала не спрашивать людей здесь?
Ответы
Ответ 1
В стандартной библиотеке нет коллекции Java. LinkedHashSet<E>
сохраняет упорядочение аналогично List
, поэтому, если вы завернете свой набор в List
, когда хотите использовать это как List
вы получите семантику, которую хотите.
В качестве альтернативы Commons Collections (или commons-collections4
для общей версии) имеет List
, который делает то, что вы хотите уже: SetUniqueList
/SetUniqueList<E>
.
Ответ 2
Итак, вот что я сделал в конце концов. Надеюсь, это поможет кому-то другому.
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);
}
}
}
Ответ 3
Вот что я сделал, и он работает.
Предполагая, что у меня есть ArrayList
для работы с первым, что я сделал, был создан новый LinkedHashMap
.
LinkedHashSet<E> hashSet = new LinkedHashSet<E>()
Затем я пытаюсь добавить свой новый элемент в LinkedHashSet
. Метод добавления не изменяет LinkedHasSet
и возвращает false, если новый элемент является дубликатом. Таким образом, это условие, которое я могу проверить перед добавлением в ArrayList
.
if (hashSet.add(E)) arrayList.add(E);
Это простой и элегантный способ предотвратить добавление дубликатов в список массивов. Если вы хотите, вы можете инкапсулировать его и переопределить метод add в классе, который расширяет ArrayList
. Просто помните, что нужно иметь дело с addAll
, перейдя через элементы и вызывая метод добавления.
Ответ 4
Вы должны серьезно рассмотреть ответ dhiller:
- Вместо того, чтобы беспокоиться о добавлении ваших объектов в список, не содержащий дубликатов, добавьте их в Set (любая реализация), которая по своей природе будет фильтровать дубликаты.
- Когда вам нужно вызвать метод, требующий List, оберните его в
new ArrayList(set)
(или a new LinkedList(set)
, что угодно).
Я думаю, что решение, которое вы разместили с NoDuplicatesList
, имеет некоторые проблемы, в основном с помощью метода contains()
, а также ваш класс не обрабатывает проверку дубликатов в коллекции, переданной вашему методу addAll()
.
Ответ 5
Почему бы не инкапсулировать набор со списком, вроде как:
new ArrayList( new LinkedHashSet() )
Это оставляет другую реализацию для кого-то, кто является настоящим мастером коллекций; -)
Ответ 6
Мне нужно было что-то вроде этого, поэтому я пошел в коллекцию commons и использовал SetUniqueList, но когда я запустил некоторый тест производительности, я обнаружил, что он не оптимизирован по сравнению с случаем, если я хочу использовать Set и получить Массив с использованием метода Set.toArray(), SetUniqueTest занял 20: 1 раз, чтобы заполнить, а затем пересечь 100 000 строк по сравнению с другой реализацией, что является большой разницей, поэтому, если вы беспокоитесь об эффективности, я рекомендую вам использовать Set и получить 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
}
Отношения
Мохаммед Слейм
http://abusleem.net/blog
Ответ 7
Документация для интерфейсов коллекции:
Set - коллекция, которая не может содержать повторяющиеся элементы.
Список - упорядоченная коллекция (иногда называемая последовательностью). Списки могут содержать повторяющиеся элементы.
Итак, если вы не хотите дубликатов, вы, вероятно, не должны использовать список.
Ответ 8
Сверху моей головы списки позволяют дублировать. Вы можете быстро реализовать UniqueArrayList
и переопределить все функции add
/insert
, чтобы проверить contains()
перед вызовом унаследованных методов. Для личного использования вы можете использовать только метод add
, который вы используете, и переопределить остальные, чтобы исключить исключение, если будущие программисты попытаются использовать список другим способом.
Ответ 9
в add
, почему бы не использовать HashSet.add()
для проверки дубликатов вместо HashSet.consist()
.
HashSet.add()
вернет true
, если нет дубликата и false
в противном случае.
Ответ 10
ПРИМЕЧАНИЕ. В него не включена реализация 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));
}
}
Ответ 11
Я просто сделал свой собственный 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, а также массив объектов.