Java 从arraylist中删除重复项

Java 从arraylist中删除重复项,java,arraylist,Java,Arraylist,我正在尝试从arraylist中删除重复的对象 见下面的代码: ArrayList<Customer> customers=new ArrayList<Customer>(); for(int i=0;i<accounts.size();i++){ customers.add(accounts.get(i).getCustomer()); } for(int i=0;i<customers.size();i++){

我正在尝试从arraylist中删除重复的对象 见下面的代码:

ArrayList<Customer> customers=new ArrayList<Customer>();

    for(int i=0;i<accounts.size();i++){
        customers.add(accounts.get(i).getCustomer());
    }

    for(int i=0;i<customers.size();i++){
        for(int j=i+1;j<customers.size();j++){
            if(customers.get(i).getSocialSecurityNo().compareTo(customers.get(j).getSocialSecurityNo())==0){
                if(customers.get(i).getLastName().compareToIgnoreCase(customers.get(j).getLastName())==0){
                    if(customers.get(i).getFirstName().compareToIgnoreCase(customers.get(j).getFirstName())==0){
                        customers.remove(j);
                    }
                }
            }
    }
    }
ArrayList客户=新建ArrayList();

对于(int i=0;i是您的
int j=i+1
造成了问题。您需要在每次迭代中使用客户列表的最后一个值进行测试。

在将客户添加到上述循环的列表之前,为什么不检查

if(!cutomers.contains(accounts.get(i).getCustomer())
{
//add them if it doesn't contain
}
它应该可以避免您执行第二个循环


编辑:需要重写该方法。

基本缺陷是,由于ListArray是可变的,一旦删除一个元素,就必须重新调整索引

if(customers.get(i).getFirstName().compareToIgnoreCase(customers.get(j).getFirstName())==0){
       customers.remove(j--);
}
还可以尝试从i循环中减去一:

for(int i=0;i<customers.size()-1;i++){
    for(int j=i+1;j<customers.size();j++){
for(int i=0;icustomers=newarraylist(newhashset(customers))

确保正确执行equals和hashmethod

删除项目后尝试添加
j-->
。这将为您重新编制索引并解决问题

    public static void removeDuplicates(ArrayList list) {
            HashSet set = new HashSet(list);
            list.clear();
            list.addAll(set);
    }

覆盖适当的equals和hashcode因此,关于正确执行此操作:

您的Customer对象应该有一个and方法来进行比较(或者您只需要为每个客户提供一个Customer对象,这意味着您的数据模型必须进行调整。然后默认的hashCode/equals就可以了)

如果您有此功能,可以将三个嵌套的ifs替换为一个:

    if(customers.get(i).equals(customers.get(j)) {
       customers.remove(j);
    }
这还不能解决你的问题,但可以让你更清楚地看到它。如果 查看哪些对象与哪些其他对象进行了比较,您将看到每次删除后 对于列表中的对象,下一个对象的索引与刚才删除的对象的索引相同, 您不会将当前对象与它进行比较。正如前面所说,删除后的
j--
将解决此问题

更高性能的解决方案是使用集合(保证不包含重复项)。 在您的情况下,一个
HashSet
LinkedHashSet
(如果您关心订单) 好的

然后,您的整个代码归结为:

Set<Customer> customerSet = new HashSet<Customer>();

for(Account acc : accounts){
    customerSet.add(acc.getCustomer());
}
List<Customer> customers = new ArrayList<Customer>(customerSet);
Set customerSet=new HashSet();
会计科目(会计科目:会计科目){
customerSet.add(根据getCustomer());
}
列表客户=新阵列列表(customerSet);
如果你真的不需要一个列表(即索引访问),只需简单地修改最后一行即可
使用集合。正如其他人所提到的,我的第一个想法是使用集合。另一种方法是使用Java版本的foreach,而不是使用索引。一般方法:

public static ArrayList removeDuplicates(ArrayList origList) {
    ArrayList newList = new ArrayList();
    for (Object m : origList) {
        if (!newList.contains(m)) {
            newList.add(m);
        }
    }
    return newList;
}

在测试中,我只使用了字符串;为了类型安全,我建议在适当的地方将Customer插入到代码中。

下面的代码对我很有用。试试看。您可以根据自己的喜好操作compare方法

ArrayList客户=……;
Set customerlist=新树集(新比较器(){



将其插入到一个集合中可能重复-如果您遵循tylermac的建议(这是一个好建议)。请确保覆盖equals()和hashCode()方法。@RMT,我曾经提出过这个建议,并且是许多负面意见的焦点。:)@mre这是真的,它不是最好的使用方法,我认为它应该比下面的第二和第三个循环更好。(只是我的观点:))有很多更好的方法来解决这个问题,但这并不能回答他/她的问题。他/她的算法有什么问题吗?@RMT我尝试过这样做,但它似乎不起作用(int i=0;i@trs我忘了告诉你的是,你必须覆盖Equals方法。基本上,当(从我所知道的)客户是平等的if语句中的所有内容。j+1只是确保每个项都与自身进行比较。这就是迭代器发挥作用的地方。是的,迭代器总是更好!@Voo:迭代器在这里没有真正的帮助,你会在股票数组列表中得到ConcurrentModificationExceptions。@Paulo你可以用迭代器得到它,但是它看起来没有任何改善。所以是的,没有那么好。您应该将方法签名更改为
removeDuplicates(集合列表)
(程序到接口,而不是具体的类)。因此,我想我不能将您的方法用于
LinkedList
或任何其他非ArrayList集合。您只需复制粘贴该方法并接受另一个类类型。
LinkedList
是Java集合框架中众多集合之一。请查看并查看“所有已知实现类”下的内容对于各种
集合
实现。@Steve我不确定这与任何事情有什么关系。@nsfyn55 Java语言规范现在由Oracle驱动,因此通过使用Java,您将任由他们摆布。。。
        @Override
        public int compare(Customer c1, Customer c2) {
            return c1.getSocialSecurityNo().compareTo(c2.getSocialSecurityNo());
        }            
    });
    customerlist.addAll(customers);
    customers.clear();
    customers.addAll(customerlist);