根据自定义对象属性从数组列表中删除元素
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<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 类中实现了Comparable
和 Comparator
,效果很好。非常感谢
嘿..我已经做到了并且成功了。但是我的带有重复值的原始列表也更改为排序值。不知道为什么。请帮帮我。
最有可能的是,您没有在列表中创建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());
【讨论】:
以上是关于根据自定义对象属性从数组列表中删除元素的主要内容,如果未能解决你的问题,请参考以下文章