删除重复的ArrayList自定义对象

时间:2015-04-30 10:19:48

标签: java arraylist duplicate-removal

我有一个ArrayList,它包含类Event的元素。 事件有两个属性NameTimestamp。 该列表现在显示所有事件。 我想删除具有相同名称但不同时间戳的重复项,并将它们放在另一个列表中。这样,用户可以单击具有该名称的事件,然后选择日期。

我已经在我的应用程序中覆盖函数equals(比较名称和时间戳)以及其他一些功能。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:20)

如果您已拥有自己的等号方法,则无法使用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);
}

答案 1 :(得分:2)

我认为你正在使用错误的数据结构。您希望使用Map的实现并将String(名称)映射到Set<Event>(唯一事件)。

以下是我们测试它的方式:

  1. 创建一些活动。
  2. 创建Map<String, Set<Event>。这样我们就可以将名称映射到唯一事件。
  3. 填写地图。
  4. 首先,我们创建一个要测试的事件集合:

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

    现在我们在名称及其所有相应的唯一事件之间创建映射:

        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]
    

    提示2:

    如果这不符合您的期望,并且您希望获得不同的唯一性定义,则可以实施Comparator<Event>并将其与TreeSet<Event>一起使用,而不是使用HashSet<Event> }无法接受自定义Comparator

    所以,如果你有一个班级:

    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);
    
        }
    
    祝你好运。

答案 2 :(得分:-1)

您应该覆盖Event类中的equals()hashCode()方法,并在Set而不是List中添加所有对象。如果您已正确覆盖Setequals()hashCode()将不允许重复的对象。