Mer*_*cer 55 java collections list duplicates
我想从列表中删除重复项,但我正在做的是不起作用:
List<Customer> listCustomer = new ArrayList<Customer>();
for (Customer customer: tmpListCustomer)
{
if (!listCustomer.contains(customer))
{
listCustomer.add(customer);
}
}
Run Code Online (Sandbox Code Playgroud)
Tom*_*ine 89
假设您想要保留当前订单并且不想要aSet,也许最简单的是:
List<Customer> depdupeCustomers =
new ArrayList<>(new LinkedHashSet<>(customers));
Run Code Online (Sandbox Code Playgroud)
如果要更改原始列表:
Set<Customer> depdupeCustomers = new LinkedHashSet<>(customers);
customers.clear();
customers.addAll(dedupeCustomers);
Run Code Online (Sandbox Code Playgroud)
Ste*_*n C 48
如果该代码不起作用,您可能没有适当地equals(Object)在Customer类上实现.
据推测,有一些关键(我们称之为customerId)可以唯一地识别客户; 例如
class Customer {
private String customerId;
...
Run Code Online (Sandbox Code Playgroud)
适当的定义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);
}
Run Code Online (Sandbox Code Playgroud)
为了完整性,您还应该实现,hashCode以便两个Customer相等的对象将返回相同的哈希值.hashCode上述定义的匹配equals将是:
public int hashCode() {
return customerId.hashCode();
}
Run Code Online (Sandbox Code Playgroud)
值得注意的是,如果列表很大,这不是删除重复项的有效方法.(对于包含N个客户的列表,您将需要N*(N-1)/2在最坏的情况下执行比较;即,当没有重复时.)对于更有效的解决方案,您应该使用类似的东西HashSet来执行重复检查.
Ali*_*lah 25
java 8更新
你可以使用数组流如下:
Arrays.stream(yourArray).distinct()
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
Sco*_*nes 13
客户是否执行equals()合同?
如果不执行equals()和hashCode(),然后listCustomer.contains(customer)将检查,看看是否完全相同的情况下在列表中已经存在(比如通过我的意思是完全相同的对象-内存地址等).如果您要查找的是测试同一客户(如果他们拥有相同的客户名称或客户编号,可能是同一客户)是否已在列表中,那么您需要覆盖equals()以确保它检查相关字段(例如客户名称)是否匹配.
注意:hashCode()如果您要覆盖,请不要忘记覆盖equals()!否则,您可能会遇到HashMaps和其他数据结构的问题.为了更好地了解为什么会这样,以及要避免哪些陷阱,请考虑查看Josh Bloch的Effective Java章节equals()和hashCode()(该链接仅包含有关您实施hashCode()时必须实现的原因的iformation equals(),但有关如何覆盖的良好报道equals()太).
顺便问一下,您的套装是否有订购限制?如果没有,解决这个问题的一种稍微简单的方法是使用Set<Customer>如下:
Set<Customer> noDups = new HashSet<Customer>();
noDups.addAll(tmpListCustomer);
return new ArrayList<Customer>(noDups);
Run Code Online (Sandbox Code Playgroud)
哪个会很好地删除重复项,因为集合不允许重复.但是,这将失去任何应用的排序tmpListCustomer,因为HashSet没有明确的排序(你可以通过使用a TreeSet,但这与你的问题不完全相关).这可以简化您的代码.
我怀疑你可能没有Customer.equals()正确实施(或根本没有).
List.contains()用于equals()验证其任何元素是否与作为参数传递的对象相同.但是,equals物理身份测试的默认实现,而不是值身份.因此,如果您没有覆盖它Customer,它将为具有相同状态的两个不同Customer对象返回false.
以下是如何实现equals的细节(以及hashCode哪一个 - 如果您需要实现其中任何一个,您必须实际上始终实现这两者).由于您尚未向我们展示Customer类,因此很难提供更具体的建议.
正如其他人所指出的那样,你最好使用Set而不是手工完成工作,但即便如此,你仍然需要实现这些方法.
小智 6
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());
}
Run Code Online (Sandbox Code Playgroud)
"contains"方法搜索列表是否包含从Customer.equals(Object o)返回true的条目.如果您没有在Customer或其父项之一中重写equals(Object),那么它将仅搜索同一对象的现有匹配项.这可能是你想要的,在这种情况下你的代码应该工作.但是,如果您正在寻找没有两个对象同时代表同一个客户,那么在这种情况下,您需要覆盖equals(Object)以返回true.
使用Set而不是List的一个实现也可以自动,快速地为您提供重复删除(除了非常小的列表之外的任何其他内容).您仍然需要提供equals代码.
覆盖equals()时,还应覆盖hashCode().