【发布时间】: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<ScheduleElement>。这样你就可以摆脱无用和不可实现的compare。 +++ 我猜,ConcurrentSkipListMap是你想要的Map。请注意,几乎每个 Java 集都基于映射。
标签: java performance set thread-safety comparator