java 删除重复的 ArrayList 自定义对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29965140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove duplicates ArrayList custom object
提问by Nicolas Zawada
I have an ArrayList which contains element of a class Event
.
Event has two properties, Name
and Timestamp
.
The list now shows ALL events.
I want to remove the duplicates with the same name, but different timestamp, and put them in another list. This way the user can click on an event with that name, then select a date.
我有一个包含类元素的 ArrayList Event
。事件有两个属性,Name
和Timestamp
。该列表现在显示所有事件。我想删除具有相同名称但时间戳不同的重复项,并将它们放在另一个列表中。通过这种方式,用户可以单击具有该名称的事件,然后选择一个日期。
I am already overriding the function equals (that compares name AND timestamp) for some other functionalities in my application.
我已经为我的应用程序中的一些其他功能覆盖了函数 equals(比较名称和时间戳)。
How can I solve this?
我该如何解决这个问题?
回答by Jordi Castilla
If you already have your own equals method you can't use Hash
collections. You must manually check it implementing a nested loop:
如果您已经拥有自己的 equals 方法,则不能使用Hash
集合。您必须手动检查它是否实现了嵌套循环:
List<Event> allEvents = // fill with your events.
List<Event> noRepeat = new ArrayList<Event>();
for (Event event : allEvents) {
boolean isFound = false;
// check if the event name exists in noRepeat
for (Event e : noRepeat) {
if (e.getName().equals(event.getName()) || (e.equals(event))) {
isFound = true;
break;
}
}
if (!isFound) noRepeat.add(event);
}
回答by Reut Sharabani
I think you're using the wrong data structure. You want to use an implementation of Map
and map String
(name) to Set<Event>
(unique events).
我认为您使用了错误的数据结构。您想使用Map
和映射String
(名称)到Set<Event>
(唯一事件)的实现。
Here is how we test it:
下面是我们测试它的方法:
- Create some events.
- Create
Map<String, Set<Event>
. this will allow us to map a name to uniqueevents. - Fill the mapping.
- 创建一些事件。
- 创建
Map<String, Set<Event>
. 这将允许我们将名称映射到唯一事件。 - 填充映射。
So first, we create a collection of events to test:
所以首先,我们创建一个事件集合来测试:
Collection<Event> events = new ArrayList<Event>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add(new Event("FirstCategory", new Timestamp(0)));
add(new Event("FirstCategory", new Timestamp(0)));
add(new Event("FirstCategory", new Timestamp(1)));
add(new Event("SecondCategory", new Timestamp(2)));
}
};
Now we create a mapping between a name and all of it's corresponding uniqueevents:
现在我们创建一个名字和它所有对应的唯一事件之间的映射:
Map<String, Set<Event>> eventsByName = new HashMap<String, Set<Event>>();
Now we fill the mapping with unique events for each name:
现在我们用每个名称的唯一事件填充映射:
for (Event e : events) {
if (!eventsByName.containsKey(e.getName())) {
// create new set by name
eventsByName.put(e.getName(), new HashSet<Event>());
}
// add event to existing Set.
// duplicates will be dropped since it's a `Set`
eventsByName.get(e.getName()).add(e);
}
Check what we got:
检查我们得到了什么:
System.out.println(eventsByName);
Output:
输出:
{
SecondCategory=[
Event [name=SecondCategory, timestamp=1970-01-01 02:00:00.002]
],
FirstCategory=[
Event [name=FirstCategory, timestamp=1970-01-01 02:00:00.0],
Event [name=FirstCategory, timestamp=1970-01-01 02:00:00.001]
]
}
Tip 1:
提示 1:
To get the list of names you only need to look at the Map
's keys, which are effectively a Set
as well:
要获取名称列表,您只需查看Map
的键,它们实际上也是 a Set
:
System.out.println(eventsByName.keySet());
Output:
输出:
[SecondCategory, FirstCategory]
Tip 2:
提示 2:
If this isn't what you expect, and you want a different definition of uniqueness, you can implement a Comparator<Event>
and use that with a TreeSet<Event>
instead of using the HashSet<Event>
which can not accept a custom Comparator
.
如果这不是您所期望的,并且您想要一个不同的唯一性定义,您可以实现 aComparator<Event>
并将其与 a 一起使用,TreeSet<Event>
而不是使用HashSet<Event>
不能接受自定义的Comparator
。
So if you have a class:
所以如果你有一堂课:
class EventByRandomDefinitionComparator implements Comparator<Event>{
// implementation ...
}
This is all that needs to be done when filling the mapping:
这就是填充映射时需要完成的全部工作:
// create different comparison mechanism
Comparator<Event> comparator = new EventByRandomDefinitionComparator();
for (Event e : events) {
if (!eventsByName.containsKey(e.getName())) {
// create new set by name
// changed Set implementation to use new comparator
eventsByName.put(e.getName(), new TreeSet<Event>(comparator)));
}
// add event to existing Set.
// duplicates will be dropped since it's a `Set`
eventsByName.get(e.getName()).add(e);
}
Good luck.
祝你好运。
回答by Aakash
You should override your equals()
and hashCode()
methods in your Event class and add all the objects in a Set
rather than a List
. A Set
will not allow the duplicate objects, provided you have properly overridden the equals()
and hashCode()
.
您应该覆盖Event 类中的equals()
和hashCode()
方法,并将所有对象添加到 aSet
而不是List
. ASet
将不允许重复的对象,前提是您已正确覆盖equals()
和hashCode()
。