删除重复的 ArrayList 自定义对象
Remove duplicates ArrayList custom object
我有一个 ArrayList,其中包含 class Event
的元素。
事件有两个属性,Name
和 Timestamp
。
该列表现在显示所有事件。
我想删除具有相同名称但不同时间戳的重复项,并将它们放在另一个列表中。这样,用户可以单击具有该名称的事件,然后 select 日期。
我已经为我的应用程序中的一些其他功能覆盖了 equals 函数(比较名称和时间戳)。
我该如何解决这个问题?
如果您已经有自己的 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);
}
您应该在事件 class 中覆盖 equals()
和 hashCode()
方法,并将所有对象添加到 Set
而不是 List
中。如果您已正确覆盖 equals()
和 hashCode()
.
,Set
将不允许重复对象
我认为您使用了错误的数据结构。您想使用 Map
的实现并将 String
(名称)映射到 Set<Event>
(唯一事件)。
以下是我们的测试方法:
- 创建一些事件。
- 创建
Map<String, Set<Event>
。这将允许我们将名称映射到 unique 事件。
- 填写映射。
所以首先,我们创建一个事件集合来测试:
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)));
}
};
现在我们创建一个名称和所有对应的 unique 事件之间的映射:
Map<String, Set<Event>> eventsByName = new HashMap<String, Set<Event>>();
现在我们用每个名字的唯一事件填充映射:
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);
}
检查我们得到了什么:
System.out.println(eventsByName);
输出:
{
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]
]
}
提示 1:
要获取名称列表,您只需查看 Map
的键,它们实际上也是 Set
:
System.out.println(eventsByName.keySet());
输出:
[SecondCategory, FirstCategory]
技巧二:
如果这不是您所期望的,并且您想要不同的唯一性定义,您可以实现 Comparator<Event>
并将其与 TreeSet<Event>
一起使用,而不是使用 HashSet<Event>
不能接受自定义 Comparator
.
所以如果你有 class:
class EventByRandomDefinitionComparator implements Comparator<Event>{
// implementation ...
}
这就是填充映射时需要完成的全部工作:
// 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);
}
祝你好运。
我有一个 ArrayList,其中包含 class Event
的元素。
事件有两个属性,Name
和 Timestamp
。
该列表现在显示所有事件。
我想删除具有相同名称但不同时间戳的重复项,并将它们放在另一个列表中。这样,用户可以单击具有该名称的事件,然后 select 日期。
我已经为我的应用程序中的一些其他功能覆盖了 equals 函数(比较名称和时间戳)。
我该如何解决这个问题?
如果您已经有自己的 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);
}
您应该在事件 class 中覆盖 equals()
和 hashCode()
方法,并将所有对象添加到 Set
而不是 List
中。如果您已正确覆盖 equals()
和 hashCode()
.
Set
将不允许重复对象
我认为您使用了错误的数据结构。您想使用 Map
的实现并将 String
(名称)映射到 Set<Event>
(唯一事件)。
以下是我们的测试方法:
- 创建一些事件。
- 创建
Map<String, Set<Event>
。这将允许我们将名称映射到 unique 事件。 - 填写映射。
所以首先,我们创建一个事件集合来测试:
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)));
}
};
现在我们创建一个名称和所有对应的 unique 事件之间的映射:
Map<String, Set<Event>> eventsByName = new HashMap<String, Set<Event>>();
现在我们用每个名字的唯一事件填充映射:
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);
}
检查我们得到了什么:
System.out.println(eventsByName);
输出:
{
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]
]
}
提示 1:
要获取名称列表,您只需查看 Map
的键,它们实际上也是 Set
:
System.out.println(eventsByName.keySet());
输出:
[SecondCategory, FirstCategory]
技巧二:
如果这不是您所期望的,并且您想要不同的唯一性定义,您可以实现 Comparator<Event>
并将其与 TreeSet<Event>
一起使用,而不是使用 HashSet<Event>
不能接受自定义 Comparator
.
所以如果你有 class:
class EventByRandomDefinitionComparator implements Comparator<Event>{
// implementation ...
}
这就是填充映射时需要完成的全部工作:
// 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);
}
祝你好运。