如何向List添加新的唯一元素

时间:2013-08-23 09:00:12

标签: java

我有一个100000对象列表。和它独特的清单。我想要添加一个新对象。但是要添加的条件是它应该是唯一的含义,如果新元素已经在列表中,则不应该添加到列表中并且应该抛出异常。如果有想法,请告诉我。

6 个答案:

答案 0 :(得分:1)

如果您有充分的理由使用List,例如,因为订单对您很重要,只需使用contains检查您要添加的元素是否已在列表中:

public void addUnique(Object element) throws NotUniqueException {
    if (list.contains(element)) {
        throw new NotUniqueException(list, element);
    } else {
        list.add(element);
    }
}

但是,对于100,000个对象,contains会很慢,因为它必须执行线性搜索。

另一种方法是,如果您的列表以某种自然顺序存储您的对象,例如,可以用java.util.Comparator描述的订单。在这种情况下,您可以使用二进制搜索来减少从O(n)到O(log(n))的搜索,而不是使用contains

public void addUnique(Object element) throws NotUniqueException {
    int index = Collections.binarySearch(list, element, comparator);
    if (index >= 0) {
        throw new NotUniqueException(list, element);
    } else {
        list.add(index, element);
    }
}

然而,缺点是您的add现在变得更加昂贵,因为为了保持列表排序,必须移动一些元素以为新元素腾出空间。这使您的add成为线性操作。

为您提供订单和快速contains以及快速add的数据结构是一个排序树,因此您可能想要评估这是否适合您。

最后,您可以将SetList结合起来,即存储两者中的每个元素:该集合为您提供快速contains,同时列表保留元素的顺序。使用这种方法,您不仅限于Comparator定义的特定订单,而是可以简单地使用插入顺序:

public void addUnique(Object element) throws NotUniqueException {
    if (set.contains(element)) {
        throw new NotUniqueException(list, element);
    } else {
        list.add(element);
        set.add(element);
    }
}

这基本上是LinkedHashSet为你做的事情 - 另见Peter Walser的答案。

答案 1 :(得分:0)

您可以使用一个集合,它只包含唯一结果http://docs.oracle.com/javase/7/docs/api/java/util/Set.html

由于

答案 2 :(得分:0)

您应该使用Set而不是List

但是你可以得到它 -

List<Object> list =...;
public boolean add(Object obj){
    Set<Object> set = new HashSet<>(list);
    return set.add(obj);
}

答案 3 :(得分:0)

您需要根据您的要求使用Set数据结构。但是如果你试图添加新的副本,它不会抛出异常。

如果您已有列表,则可以使用

创建Set
Set<YourType> foo = new HashSet<YourType>(yourList);

答案 4 :(得分:0)

使用Set代替List。如果你真的想要一个List,请考虑以下示例。

   List<String> myList=new ArrayList<>();
    myList.add("asd");
    myList.add("asf");
    myList.add("asf");
    Set<String> set=new HashSet<>();
    set.addAll(myList);
    set.add("newString");
    myList.clear();
    myList.addAll(set);

答案 5 :(得分:0)

如果插入顺序很重要,请改用LinkedHashSet,这基本上是一个集合,但也跟踪列表中的元素,以允许按照插入的顺序迭代元素(与列表一样) )。

对于尝试添加重复元素时的异常,您可以通过验证add(..)方法返回true来检查是否添加了元素,否则抛出Exception,或者通过创建一个专门的子类来执行此检查:

public class UniqueItemList <E> extends LinkedHashSet<E> {

    @Override
    public boolean add (E e) {
        checkContains(e);
        return super.add(e);
    };

    @Override
    public boolean addAll (Collection<? extends E> collection) {
        for (E e : collection) {
            add(e);
        }
        return !collection.isEmpty();
    }

    private void checkContains (E e) {
        if (contains(e)) {
            throw new IllegalArgumentException("Element was already added");
        }
    }
}