我有一个100000对象列表。和它独特的清单。我想要添加一个新对象。但是要添加的条件是它应该是唯一的含义,如果新元素已经在列表中,则不应该添加到列表中并且应该抛出异常。如果有想法,请告诉我。
答案 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
的数据结构是一个排序树,因此您可能想要评估这是否适合您。
最后,您可以将Set
与List
结合起来,即存储两者中的每个元素:该集合为您提供快速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");
}
}
}