根据自定义对象属性从数组列表中删除元素

Posted

技术标签:

【中文标题】根据自定义对象属性从数组列表中删除元素【英文标题】:removing element from arraylist depending on a custom object property 【发布时间】:2013-05-17 11:07:30 【问题描述】:

我有一个带有自定义对象的 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 应该可以工作 在迭代时删除通常是个坏主意......也许最好创建一个单独的列表并将预期结果过滤(添加)到新列表中。 为什么在迭代时删除是个坏主意?如果仅从一个线程访问它,这是一个好主意。如果不是,您还有其他问题 【参考方案1】:

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

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

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

【讨论】:

将对象与下一个对象进行比较 此外,下一个对象不会与第三个对象进行比较。第四个对象不会与第五个对象比较 ....【参考方案2】:

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

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

【讨论】:

【参考方案3】:

我有同样的情况,我想出了这个解决方案来使用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());
    
);

现在,如果您将Person 插入您的persons,则不会插入重复项(基于它们的name 属性)。

因此,您可以迭代 list&lt;Person&gt; 并将其中的每个项目插入到您的 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,效果很好。非常感谢 嘿..我已经做到了并且成功了。但是我的带有重复值的原始列表也更改为排序值。不知道为什么。请帮帮我。 最有可能的是,您没有在列表中创建copy,而是将它们直接放入您的sorted-set。这听起来可能有点琐碎,但最好有一个 for-loop 并将每个元素复制到新集合中,以保留您的第一个列表。【参考方案4】:

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

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());
     

【讨论】:

以上是关于根据自定义对象属性从数组列表中删除元素的主要内容,如果未能解决你的问题,请参考以下文章

【JS】数组对象自定义排序

自定义可序列化对象数组列表的意图错误

如何从自定义模型对象数组中获取特定键的值

根据索引从数组中删除对象

NSPredicate 根据嵌套结构中的属性过滤自定义对象

从 NSMutableArray 中删除重复的自定义对象,确保保留最新的重复对象