Java 删除重复元素 对象_关于java:删除重复的ArrayList自定义对象

本问题已经有最佳答案,请猛点这里访问。

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

对于我的应用程序中的其他一些功能,我已经重写了equals函数(用于比较名称和时间戳)。

我怎么解决这个问题?

您是否尝试使用hashset而不是arraylist?

您是否有类似相同名称和时间戳的情况,并且希望将其也保存在列表中?

你必须保留哪些活动?第一次发现?

请点击这里的链接。这将显示列表的备选方案。如果可能的话,你可以走这条路。其他注释

为什么这个标记为副本?复制链接没有回答这个问题,只回答了一小部分,而基于另一部分,它做得不对。我引用:"我想删除具有相同名称但时间戳不同的重复项,并将它们放在另一个列表中。"这里的过滤似乎并不是真正的目标:"这样用户就可以点击一个具有该名称的事件,然后选择一个日期。"

如果您已经有了自己的equals方法,则不能使用Hash集合。必须手动检查它是否实现了嵌套循环:

List allEvents = // fill with your events.

List noRepeat = new ArrayList();

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

}

我认为这不是完整的解决方案。我想删除具有相同名称但时间戳不同的重复项,并将它们放在另一个列表中,您还需要检查timmestamps是否相等

他有一个equals方法来检查两个参数,他需要从一个列表中删除相同的命名事件:op说:我想删除具有相同名称但时间戳不同的重复项,这就是我的方法所做的……

是的,但是由于ArrayList可以包含重复条件,所以应该是if (e.getName().equals(event.getName() || e.equals(event))来删除同样具有相同名称和时间戳的不同对象。

事实上,这违背了自然的逻辑,但这是真的…好抓!

@jordicastilla一个很好的方法就是使用自定义的Comparator与TreeSet进行比较(使用该比较器创建一个集合)。它还加强了清晰性,因为使用正确的接口传达了这个想法。见我答案的最后一部分。

非常感谢,这解决了我的问题!!

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

下面是我们测试它的方法:

创建一些事件。

创建Map。这将允许我们将名称映射到唯一的事件。

填充映射。

因此,首先,我们创建一组要测试的事件:

Collection events = new ArrayList() {

/**

*

*/

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> eventsByName = new HashMap>();

现在,我们用每个名称的唯一事件填充映射:

for (Event e : events) {

if (!eventsByName.containsKey(e.getName())) {

// create new set by name

eventsByName.put(e.getName(), new HashSet());

}

// 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,并将其与TreeSet一起使用,而不是使用不能接受自定义Comparator的HashSet。

所以如果你有一门课:

class EventByRandomDefinitionComparator implements Comparator{

// implementation ...

}

这是填充映射时需要完成的全部工作:

// create different comparison mechanism

Comparator 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(comparator)));

}

// add event to existing Set.

// duplicates will be dropped since it's a `Set`

eventsByName.get(e.getName()).add(e);

}

祝你好运。

谢谢你的综合回答。如果我从一开始就用地图的话会容易得多。另一个答案解决了我的问题,但我会把地图记在心里,以备将来使用。我现在将使用一个映射将同一事件与多个时间戳链接起来。

无论是什么阻止你现在使用正确的解决方案,如果你添加更多基于错误实现的代码,情况会更糟。使用正确的工具可以使代码更容易维护、测试和理解。如果这个答案缺乏你想要完成的事情,那就把它添加到你的问题中,我可以尝试扩展这个答案来包含它。

您应该在事件类中重写您的equals()和hashCode()方法,并将所有对象添加到Set而不是List中。如果您正确地覆盖了equals()和hashCode(),Set将不允许复制对象。

为了另一个目的必须使用equals…请仔细阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值