Java 那里有没有重复的 List 实现吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/268672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:15:15  来源:igfitidea点击:

Is there a no-duplicate List implementation out there?

javalistcollectionsduplicates

提问by Yuval

I know about SortedSet, but in my case I need something that implements List, and not Set. So is there an implementation out there, in the API or elsewhere?

我知道SortedSet,但就我而言,我需要一些可以实现的东西List,而不是Set。那么在 API 或其他地方是否有实现?

It shouldn't be hard to implement myself, but I figured why not ask people here first?

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

采纳答案by Calum

There's no Java collection in the standard library to do this. LinkedHashSet<E>preserves ordering similarly to a List, though, so if you wrap your set in a Listwhen you want to use it as a Listyou'll get the semantics you want.

标准库中没有 Java 集合来执行此操作。但是,LinkedHashSet<E>保留类似于 a 的顺序List,因此如果您在List想要将其用作 aList时将其包装在 a 中,您将获得所需的语义。

Alternatively, the Commons Collections(or commons-collections4, for the generic version) has a Listwhich does what you want already: SetUniqueList/ SetUniqueList<E>.

或者,Commons Collections(或commons-collections4,对于通用版本)有一个List已经可以满足您的需求:SetUniqueList/ SetUniqueList<E>

回答by Daniel Hiller

Why not encapsulate a set with a list, sort like:

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

new ArrayList( new LinkedHashSet() )

This leaves the other implementation for someone who is a real master of Collections ;-)

这为真正的集合大师留下了另一个实现;-)

回答by Hauch

The documentation for collection interfacessays:

集合接口文档说:

Set — a collection that cannot contain duplicate elements.
List — an ordered collection (sometimes called a sequence). Lists can contain duplicate elements.

Set — 不能包含重复元素的集合。
列表 — 有序集合(有时称为序列)。列表可以包含重复的元素。

So if you don't want duplicates, you probably shouldn't use a list.

所以如果你不想重复,你可能不应该使用列表。

回答by Kieveli

Off the top of my head, lists allow duplicates. You could quickly implement a UniqueArrayListand override all the add/ insertfunctions to check for contains()before you call the inherited methods. For personal use, you could only implement the addmethod you use, and override the others to throw an exception in case future programmers try to use the list in a different manner.

在我的脑海里,列表允许重复。在调用继承的方法之前,您可以快速实现 aUniqueArrayList并覆盖所有要检查的add/insert函数contains()。对于个人使用,您只能实现add您使用的方法,并覆盖其他方法以抛出异常,以防将来的程序员尝试以不同的方式使用该列表。

回答by Yuval

So here's what I did eventually. I hope this helps someone else.

所以这就是我最终所做的。我希望这对其他人有帮助。

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);
        }
    }
}   

回答by matt b

You should seriously consider dhiller's answer:

您应该认真考虑 dhiller 的回答:

  1. Instead of worrying about adding your objects to a duplicate-less List, add them to a Set (any implementation), which will by nature filter out the duplicates.
  2. When you need to call the method that requires a List, wrap it in a new ArrayList(set)(or a new LinkedList(set), whatever).
  1. 与其担心将您的对象添加到无重复的 List 中,不如将它们添加到 Set(任何实现)中,这自然会过滤掉重复项。
  2. 当您需要调用需要 List 的方法时,请将其包装在 a new ArrayList(set)(或 a new LinkedList(set),等等)中。

I think that the solution you posted with the NoDuplicatesListhas some issues, mostly with the contains()method, plus your class does not handle checking for duplicates in the Collection passed to your addAll()method.

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

回答by matt b

I needed something like that, so I went to the commons collectionsand used the SetUniqueList, but when I ran some performance test, I found that it seems not optimized comparing to the case if I want to use a Setand obtain an Arrayusing the Set.toArray()method.

我需要这样的东西,所以我去了公共集合并使用了SetUniqueList,但是当我运行一些性能测试时,我发现如果我想使用 aSetArray使用该Set.toArray()方法获得 an ,它似乎没有优化。

The SetUniqueTesttook 20:1 timeto fill and then traverse 100,000 Stringscomparing to the other implementation, which is a big deal difference.

SetUniqueTest花了20:1的时间填写,然后遍历100000个字符串相对于其他实现,这是一个大问题不同。

So, if you worry about the performance, I recommend you to use the Set and Get an Arrayinstead of using the SetUniqueList, unless you really need the logic of the SetUniqueList, then you'll need to check other solutions...

所以,如果你担心性能,我建议你使用Set 和 Get an Array而不是使用SetUniqueList,除非你真的需要 的逻辑SetUniqueList,那么你需要检查其他解决方案......

Testing code main method:

测试代码主要方法

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

}

}

Regards, Mohammed Sleem

问候, 穆罕默德·斯莱姆

回答by Jonathan

I just made my own UniqueList in my own little library like this:

我刚刚在我自己的小图书馆中制作了自己的 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;
    }
}

I have a TestCollections class that looks like this:

我有一个 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);
    }
}

Works fine. All it does is it adds to a set if it does not have it already and there's an Arraylist that is returnable, as well as an object array.

工作正常。它所做的只是将它添加到一个集合中,如果它还没有它并且有一个可返回的 Arraylist 以及一个对象数组。

回答by neoreeprast

in addmethod, why not using HashSet.add()to check duplicates instead of HashSet.consist(). HashSet.add()will return trueif no duplicate and falseotherwise.

add方法中,为什么不使用HashSet.add()检查重复项而不是HashSet.consist(). 如果没有重复,否则HashSet.add()将返回。truefalse

回答by user3570018

Here is what I did and it works.

这是我所做的并且它有效。

Assuming I have an ArrayListto work with the first thing I did was created a new LinkedHashMap.

假设我有一个ArrayList工作,我做的第一件事就是创建一个新的LinkedHashMap.

LinkedHashSet<E> hashSet = new LinkedHashSet<E>()

Then I attempt to add my new element to the LinkedHashSet. The add method does not alter the LinkedHasSetand returns false if the new element is a duplicate. So this becomes a condition I can test before adding to the ArrayList.

然后我尝试将我的新元素添加到LinkedHashSet. LinkedHasSet如果新元素是重复的,则add 方法不会改变并且返回 false。所以这成为我可以在添加到ArrayList.

if (hashSet.add(E)) arrayList.add(E);

This is a simple and elegant way to prevent duplicates from being added to an array list. If you want you can encapsulate it in and override of the add method in a class that extends the ArrayList. Just remember to deal with addAllby looping through the elements and calling the add method.

这是防止将重复项添加到数组列表的简单而优雅的方法。如果需要,您可以将其封装在扩展ArrayList. 只需记住addAll通过循环遍历元素并调用 add 方法来处理。