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 并未被修改。我需要一些帮助。谢谢!

4

4 回答 4

10

我有同样的情况,我想出了这个解决方案来使用SortedSet. 在这种情况下,那些导致 set 的比较器返回 0 的对象只会在 Set 中插入一次。

这是一个例子:

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

现在,如果您将 a 插入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
于 2013-05-22T12:03:05.167 回答
2

您的代码当前已损坏,因为您仅将对象与列表中的下一个对象进行比较。要纠正您当前的方法,您需要有另一个子循环,它将每个对象与列表中的所有其他对象进行比较。这可能会使嵌套迭代器变得混乱。

一种替代方法是定义一个新列表并在您确认它们不重复后用项目填充它。这避免了嵌套迭代器。

最后,另一种选择是定义一个equals基于此属性进行比较的方法,并将对象放入Set. 也不要忘记hashCode

于 2013-05-22T11:59:12.347 回答
2

它不会删除,因为您只是将每个元素与下一个元素进行比较。您可以将名称存储在一个 HashSet 中,该 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());
     }
}
于 2013-05-22T12:04:13.577 回答
0

每次编写 .next() 时,迭代都会向前迈出 1 步。因此,假设您的列表中有 10 个人。您选择第一个人,然后使用 iterator.next() 检查下一个人。虽然您获取了第 2 个人,但迭代器现在位于第 2 个人。所以在下一次运行中,第 3 个人被提取并与第 4 个人进行比较。

您应该做的是,选择 1 个人并将他的名字与列表中所有 10 个人的名字进行比较,然后从列表中删除所有重复对象的实例。

于 2013-05-22T12:01:11.550 回答