【问题标题】:How to performantly compare and merge similar objects while adding them to a set如何在将相似对象添加到集合时高效地比较和合并相似对象
【发布时间】:2016-10-14 06:42:45
【问题描述】:

这可能有点棘手,我不确定它是否被认为是“不要”。

我的设置如下:

我得到一个包含 4 个字段(ID、时间戳、类型和值)的对象输入。我必须将那些按照时间戳顺序插入到集合中。到目前为止很容易:

ConcurrentSkipListSet<ScheduleElement> storage = new ConcurrentSkipListSet<>(new SEComparator());

现在棘手的部分是:一小部分对象来自同一个“资产”,需要合并。基本上只要有“重复”(相同的 ID、时间戳和类型),就必须通过添加值将它们合并为一个。

我可以通过两个单独的步骤轻松做到这一点。

但在这种情况下,我必须重复(相当长的)设置两次。鉴于性能相当关键,我不想这样做。

我的第一个想法是,以某种方式更改我的比较器,即在 compareTo = 0 时,对象 1 的值在比较时增加对象 2 的值。由于比较器返回 0,对象 2 被丢弃。

public class SEComparator implements Comparator {

public int compare(ScheduleElement o1, ScheduleElement o2) {
    int i = (o1.getTime().compareTo(o2.getTime()));
    if (i == 0) {
        i = (o1.getId()).compareTo(o2.getId());
        if (i == 0) {
            i = (o1.getType().compareTo(o2.getType()));
            if (i == 0) {
                o1.setValue(o1.getValue()+o2.getValue());
            }
        }
    }
    return i;
}

@Override
public int compare(Object o1, Object o2) {
    throw new UnsupportedOperationException("Not supported yet.");
}
}

现在我对编码相当缺乏经验,我什至无法开始猜测这样的 hack 是否会破坏一些完全出乎意料的东西。

这是一个完全应该避免的黑客行为吗?或者,如果没有,您是否对此类解决方案的关键点有任何经验?

【问题讨论】:

  • compare() 方法应该比较值。不允许更新/变异它们!!!一个原因是您无法控制它的调用方式,例如无论是用old, new 还是new, old 调用。尽管您现在可以让它工作,但任何其他版本的 Java 都可能会破坏代码,因为您违反compare()的使用。
  • 谢谢,所以这是“不要”。这回答了我的问题。
  • 不回答你的问题,但是:不要使用Comparator,使用Comparator&lt;ScheduleElement&gt;。这样你就可以摆脱无用和不可实现的compare。 +++ 我猜,ConcurrentSkipListMap 是你想要的 Map。请注意,几乎每个 Java 集都基于映射。

标签: java performance set thread-safety comparator


【解决方案1】:

如果您需要通过IDtimestamptype key 并更新 value 以获取具有相同 key 字段的数据,那么您需要Map,而不是 Set

注意到我是如何在上面突出显示 key 的吗?这是因为 Mapkeyvalue 组成。

因此,使用三个关键字段创建一个关键类。无论您希望地图的值仅仅是值还是完整的ScheduleElement,这完全取决于您。

【讨论】:

  • 这里不需要钥匙。该集合只是一个临时存储缓冲区,供线程获取它们需要的东西。但是必须及时填充此存储空间,因为输入来自数据库,因此与消费者相比相当慢。
  • 你说你的表现是问题所在。我刚刚告诉你如何解决这个问题。如果你拒绝接受,那是你的损失。
  • 新地图的建造不会减慢它的速度吗?我无意拒绝你的回答,我只是(还)看不到它的好处。
  • “新地图”是什么意思?我是说用Map替换Set
  • 我听到了。我选择集合的原因是:我需要有序、唯一、并发集合中的对象。我查看的所有地图都没有提供组合,这就是我选择 ConcurrentSkipListSet 的原因,确实如此。所以使用地图意味着引入一个中间步骤,我尽量避免。
猜你喜欢
  • 1970-01-01
  • 2017-09-30
  • 2021-07-10
  • 2016-11-21
  • 2018-08-28
  • 2016-06-03
  • 2018-07-29
  • 1970-01-01
  • 2018-11-20
相关资源
最近更新 更多