删除重复的 ArrayList 自定义对象

Remove duplicates ArrayList custom object

我有一个 ArrayList,其中包含 class Event 的元素。 事件有两个属性,NameTimestamp。 该列表现在显示所有事件。 我想删除具有相同名称但不同时间戳的重复项,并将它们放在另一个列表中。这样,用户可以单击具有该名称的事件,然后 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>(唯一事件)。

以下是我们的测试方法:

  1. 创建一些事件。
  2. 创建Map<String, Set<Event>。这将允许我们将名称映射到 unique 事件。
  3. 填写映射。

所以首先,我们创建一个事件集合来测试:

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

    }

祝你好运。