我想从列表中删除重复项,但我正在做的事情不起作用:
List<Customer> listCustomer = new ArrayList<Customer>();
for (Customer customer: tmpListCustomer)
{
if (!listCustomer.contains(customer))
{
listCustomer.add(customer);
}
}
答案 0 :(得分:88)
假设您想保持当前订单并且不想要Set
,可能最简单的是:
List<Customer> depdupeCustomers =
new ArrayList<>(new LinkedHashSet<>(customers));
如果您想更改原始列表:
Set<Customer> depdupeCustomers = new LinkedHashSet<>(customers);
customers.clear();
customers.addAll(dedupeCustomers);
答案 1 :(得分:48)
如果该代码不起作用,您可能没有在equals(Object)
类上适当地实现Customer
。
据推测,有一些关键字(我们称之为customerId
)可以唯一地识别客户; e.g。
class Customer {
private String customerId;
...
equals(Object)
的适当定义如下所示:
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Customer)) {
return false;
}
Customer other = (Customer) obj;
return this.customerId.equals(other.customerId);
}
为了完整性, 也应该实现hashCode
,这样两个相等的Customer
个对象将返回相同的哈希值。上述hashCode
定义的匹配equals
将为:
public int hashCode() {
return customerId.hashCode();
}
值得注意的是,如果列表很大,这不是删除重复项的有效方法。 (对于包含N个客户的列表,您需要在最坏的情况下执行N*(N-1)/2
比较;即,当没有重复时。)为了更有效的解决方案,您应该使用像HashSet
这样的事情来做重复检查。
答案 2 :(得分:25)
java 8更新
你可以使用如下的数组流:
Arrays.stream(yourArray).distinct()
.collect(Collectors.toList());
答案 3 :(得分:13)
只需将所有元素添加到Set
:它不允许重复元素。如果您之后需要列表,请在之后使用新的ArrayList(theSet)
构造函数(其中theSet
是您的结果集)。
答案 4 :(得分:13)
客户是否实施equals()
合同?
如果它没有实现equals()
和hashCode()
,则listCustomer.contains(customer)
将检查列表中是否已存在完全相同的实例(按实例我的意思是完全相同的对象 - 内存地址等)。如果您正在寻找的是测试同一个客户(如果他们拥有相同的客户名称或客户编号,可能是同一个客户)已经在列表中,那么您需要覆盖equals()
以确保它检查相关字段(例如客户名称)是否匹配。
注意:如果要覆盖hashCode()
,请不要忘记覆盖equals()
!否则,您可能会遇到HashMaps和其他数据结构的问题。为了更好地了解这是为什么以及要避免哪些陷阱,请考虑查看Josh Bloch关于equals()
和hashCode()
的{{3}}章节(该链接仅包含有关您必须实施的原因的iformation) hashCode()
当您实施equals()
时,但有关如何覆盖equals()
的良好报道。
顺便问一下,您的套装是否有订购限制?如果没有,则解决此问题的一种稍微简单的方法是使用Set<Customer>
,如下所示:
Set<Customer> noDups = new HashSet<Customer>();
noDups.addAll(tmpListCustomer);
return new ArrayList<Customer>(noDups);
这将很好地删除重复项,因为集合不允许重复。但是,这会丢失应用于tmpListCustomer
的任何排序,因为HashSet
没有明确的排序(您可以使用TreeSet
解决这个问题,但这与您的问题不完全相关)。这可以简化您的代码。
答案 5 :(得分:9)
我怀疑你可能没有Customer.equals()
正确实施(或根本没有)。
List.contains()
使用equals()
来验证其任何元素是否与作为参数传递的对象相同。但是,equals
的默认实现测试物理身份,而不是值身份。因此,如果您未在Customer
中覆盖它,则对于具有相同状态的两个不同Customer对象,它将返回false。
以下是how to implement equals
(和hashCode
的细节 - 这是它的配对 - 如果你需要实现其中任何一个,你必须实际上始终实现这两者。由于您没有向我们展示客户类,因此很难提供更具体的建议。
正如其他人所说,你最好不要手工使用套装而不是手工完成工作,但即便如此,你仍然需要实施这些方法。
答案 6 :(得分:5)
“contains”方法搜索列表是否包含从Customer.equals(Object o)返回true的条目。如果您没有在Customer或其父项之一中重写equals(Object),那么它将仅搜索同一对象的现有匹配项。这可能是你想要的,在这种情况下你的代码应该工作。但是,如果您正在寻找没有两个对象代表同一个客户,那么在这种情况下,您需要覆盖equals(Object)以返回true。
使用Set而不是List的实现之一也可以自动,快速地为您提供重复删除(对于非常小的列表以外的任何内容)。您仍然需要提供equals代码。
当你重写equals()时,你也应该覆盖hashCode(。)。
答案 7 :(得分:5)
private void removeTheDuplicates(List<Customer>myList) {
for(ListIterator<Customer>iterator = myList.listIterator(); iterator.hasNext();) {
Customer customer = iterator.next();
if(Collections.frequency(myList, customer) > 1) {
iterator.remove();
}
}
System.out.println(myList.toString());
}
答案 8 :(得分:3)
两个建议:
使用HashSet而不是ArrayList。如果您有一个长列表
确保Customer.equals()和Customer.hashCode()正确实现,即它们应基于客户对象中基础字段的组合值。
答案 9 :(得分:3)
几乎所有上述答案都是正确的,但我建议在创建相关列表时使用Map或Set,而不是在获得性能之后。因为将列表转换为Set或Map然后再将其重新转换为List是一项微不足道的工作。
示例代码:
Set<String> stringsSet = new LinkedHashSet<String>();//A Linked hash set
//prevents the adding order of the elements
for (String string: stringsList) {
stringsSet.add(string);
}
return new ArrayList<String>(stringsSet);
答案 10 :(得分:1)
正如其他人所提到的,你可能没有正确实现equals()。
但是,您还应注意,此代码被认为效率很低,因为运行时可能是平方元素的数量。
您可能需要考虑使用Set结构而不是List,或者首先构建Set然后将其转换为列表。
答案 11 :(得分:1)
最干净的方式是:
List<XXX> lstConsultada = dao.findByPropertyList(YYY);
List<XXX> lstFinal = new ArrayList<XXX>(new LinkedHashSet<GrupoOrigen>(XXX));
并覆盖hascode
和equals
覆盖每个实体的ID属性
答案 12 :(得分:1)
恕我直言,如何做到这一天最好的方法:
假设您有一个收藏品&#34; dups &#34;并且您想要创建另一个包含相同元素的集合,但删除了所有重复项。下面的单线程就行了。
Collection<collectionType> noDups = new HashSet<collectionType>(dups);
它的工作原理是创建一个Set,根据定义,它不能包含重复项。
基于oracle doc。
答案 13 :(得分:0)
Java的正确答案是使用Set。如果您已经有List<Customer>
并想要复制它
Set<Customer> s = new HashSet<Customer>(listCustomer);
其他只是直接使用Set
实施HashSet
,TreeSet
并跳过List
构建阶段。
您需要覆盖Set
中放置的域类的hashCode()
and equals()
,以确保您想要的行为实际上是您所获得的。 equals()
可以像比较对象的唯一ID一样简单,就像比较每个字段一样复杂。 hashCode()
可以像返回唯一ID“hashCode()
表示的String
或hashCode()
一样简单。
答案 14 :(得分:0)
使用java 8 stream api。
List<String> list = new ArrayList<>();
list.add("one");
list.add("one");
list.add("two");
System.out.println(list);
Collection<String> c = list.stream().collect(Collectors.toSet());
System.out.println(c);
输出:
在价值观之前:[一,二,二]
价值观之后:[一,二]