我知道关于 SortedSet, ,但就我而言,我需要一些实现 List, , 并不是 Set. 。那么 API 或其他地方是否有实现呢?

自己实现应该不难,但我想为什么不先问问这里的人呢?

有帮助吗?

解决方案

标准库中没有 Java 集合来执行此操作。 LinkedHashSet<E> 与保留排序类似 List, ,但是,如果你将你的集合包裹在一个 List 当你想用它作为 List 你会得到你想要的语义。

或者, 公共收藏 (或者 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);

这是一种防止将重复项添加到数组列表中的简单而优雅的方法。如果您愿意,可以将其封装在扩展类中并重写 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);
        }
    }
}   

你应该认真考虑迪勒的回答:

  1. 不用担心将对象添加到无重复列表中,而是将它们添加到 Set (任何实现)中,这会自然地过滤掉重复项。
  2. 当你需要调用需要List的方法时,将其包装在一个 new ArrayList(set) (或一个 new LinkedList(set), , 任何)。

我认为您发布的解决方案是 NoDuplicatesList 有一些问题,主要是与 contains() 方法,加上你的类不处理传递给你的集合中的重复项检查 addAll() 方法。

为什么不用列表封装一个集合,排序如下:

new ArrayList( new LinkedHashSet() )

这将其他实现留给了真正的集合大师;-)

我需要类似的东西,所以我去了公共集合并使用了 SetUniqueList,但是当我运行一些性能测试时,我发现与我想使用 Set 并使用 Set 获取 Array 的情况相比,它似乎没有优化Set.toArray() 方法,与其他实现相比,SetUniqueTest 需要 20:1 的时间来填充然后遍历 100,000 个字符串,这是一个很大的差异,所以如果您担心性能,我建议您使用 Set 和获取一个Array而不是使用SetUniqueList,除非你真的需要SetUniqueList的逻辑,那么你需要检查其他解决方案......

测试代码主要方法:

公共静态无效主(字符串[] 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

笔记:它不需要 子列表 考虑到实施。

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 否则。

在我的脑海中,列表允许重复。您可以快速实施 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 以及一个对象数组。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top