根据自定义对象属性从ArrayList中删除元素

5

我有一个包含自定义对象的ArrayList。我想根据自定义对象的名称属性从数组中删除重复项。我尝试使用Set person = new TreeSet(); 完成此操作,但它不起作用。我想这是因为集合比较的是地址或其他与名称属性不相关的东西。所以我现在尝试使用迭代器,但它也没有删除重复项。以下是我的代码:

ArrayList<Person> people = new ArrayList<Person>();
Iterator<Person> iterator = people.iterator();
while (iterator.hasNext()) {
   Person person = iterator.next();

   if (person.getName().equals(iterator.next().getName())) {
       iterator.remove();
   }
}
for (Person person : people) {
    System.out.println(person.getName());
}

我看到 ArrayList 中有重复的内容,但它并没有被修改。我需要一些帮助。谢谢!


这个人是否实现了equals和hashcode方法?如果你实现了equals和hashcode,那么Set应该可以正常工作。 - Liviu Stirb
通常在迭代时删除元素是一个坏主意...可能更好的做法是创建一个单独的列表并过滤(添加)预期结果到新列表中。 - vikingsteve
为什么在迭代时删除元素是个坏主意?如果只从一个线程访问,那是个好主意。但如果不是,你会遇到其他问题。 - tgkprog
4个回答

10

我也曾遇到过同样的情况,我的解决方案是使用SortedSet。在这种情况下,那些导致集合比较器返回0的对象,只会被插入一次。

以下是一个示例:

SortedSet<Person> persons = new TreeSet<Person>(new Comparator<Person>() {
    @Override
    public int compare(Person arg0, Person arg1) {
        return arg0.getName().compareTo(arg1.getName());
    }
});

现在,如果您将一个Person对象插入到persons中,那么基于它们的name属性的重复项将不会被插入。

因此,您可以迭代遍历您的list<Person>,并将其中的每个项目插入到您的persons集合中,并确保您不会有任何重复项。所以剩下的部分将像这样:

Iterator<Person> iterator = people.iterator();
while(iterator.hasNext()) {
    persons.add(iterator.next());
}
people.clear();
people.addAll(persons); //Now, your people does not contain duplicate names

我在我的Person类中实现了ComparableComparator,它运行得非常好。非常感谢。 - madcoderz
嘿..我已经完成了这个任务并且成功运行了。但是我的原始列表中有重复的数值,也变成了排序后的数值。不知道为什么。请帮帮我。 - Arun PS
很可能,你把列表中的元素直接放入了你的“排序集合”中,而不是制作一个列表的副本。这听起来可能有点琐碎,但最好使用一个“for循环”将每个单独的元素复制到你的新集合中,以保留你的第一个列表。 - Matin Kh

2

由于您只是将每个元素与下一个元素进行比较,因此它不会被删除。您可以将名称存储在HashSet中,该集合只能保存每个字符串的一个副本,然后如果其名称已经在集合中,则删除该项。

HashSet<String> seen = new HashSet<String>();
while (iterator.hasNext()) {
     Person p = iterator.next();
     if (seen.contains(p.getName())) {
           iterator.remove();
     } else { 
           seen.add(p.getName());
     }
}

2
您的代码目前存在问题,因为您只将对象与列表中的下一个对象进行比较。要纠正您当前的方法,您需要另一个子循环,将每个对象与列表中的所有其他对象进行比较。这可能会导致嵌套迭代器混乱。
一种替代方案是定义一个新列表,并在确认它们不是重复项后填充它们。这样可以避免嵌套迭代器。
最后,另一种选择是定义一个基于此属性进行比较并将对象放入Setequals方法。别忘了hashCode

将对象与下一个对象进行比较。此外,下一个对象不会与第三个对象进行比较。第四个对象不会与第五个对象进行比较... - johnchen902

0
每次使用 .next() 方法时,迭代器都会向前移动一步。例如,你有一个包含 10 个人的列表。你选择第一个人,并使用 iterator.next() 检查下一个人。虽然你获取了第二个人,但是迭代器现在已经到达第二个人。因此,在下一次运行中,将获取第三个人并与第四个人进行比较。
你应该做的是,选择一个人并将其姓名与列表中所有 10 个人的姓名进行比较,然后从列表中删除所有重复对象的实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接