【发布时间】:2020-10-12 20:00:30
【问题描述】:
首先我需要一些非常有效的解决方案,因为我正在比较具有 >300k 元素的集合。
一开始我们有两个不同的类
Class A {
String keyA;
String keyB;
String keyC;
}
Class B {
String keyA;
String keyB;
String keyC;
String name;
String code;
toA() {
return new A(keyA, keyB, keyC);
}
}
它们都包含几个组成键的字段(在此示例中,三列键 = keyA keyB keyC)
这个组合键使得使用嵌套循环的原始蛮力计算非常长。 所以我发现最有效的方法是使用方法 toA 将第二类转换为第一类 然后我可以使用例如 google 的 api 使用 Sets 效率安全地比较它们
Set<A> collectionA = <300k of elements>
Set<B> collectionB = <300k of elements>
Set<A> collectionBConvertedToA = collectionB.stream().map(item -> item.toA()).collect(toSet())
Set<A> result = Sets.differences(collectionBConvertedToA, collectionA); // very fast first full scan comparison
Set<String> changedNames = result.stream()
.map(outer -> collectionB.stream()
// very slow second full scan comparison
.filter(inner -> inner.getKeyA().equals(outer.getKeyA())
&& inner.getKeyB().equals(outer.getKeyB())
&& inner.getKeyC().equals(outer.getKeyC()))
.findFirst()
.map(item -> item.getName()))
.collect(toSet());
log.info("changed names" + changedNames);
Guava Sets.differences 可以在不到 1/10 秒的时间内找到大于 300k 的 Sets 的差异,但后来我仍然进行全面扫描以收集名称。
我只是猜测,但有没有类似的东西
Set<B> result = Sets.differences(setA, setB, a -> a.customHashCode(), b -> b.customHashCode(), (a, b) -> a.customEquals(b))
使用自定义 hashCode 和自定义 equals 方法来保持 Sets 效率,或者有一些更好的模式来进行这种比较,因为我认为这似乎是常见问题?
编辑 我刚刚发现我可以将转换转换为扩展类
toB() {
return new B(keyA, keyB, keyC, null, null);
}
但是我需要覆盖 hashCode 和 equals 以仅使用这 3 个字段,我仍然相信有更优雅的方式
【问题讨论】:
-
您的
B.toA()没有投射B实例。相反,它创建了一个全新的A,其属性值取自B。如果可以在这些类型之间进行转换(它不是),那么这比转换成本要高得多。尽管如此,这可能是一个合理的前进方向,但请确保您了解这里实际发生的情况。 -
确实,但我只是用错了词。我编辑了帖子,谢谢。
-
我已将
collectionBConvertedToA的类型编辑为Set<A>
标签: java algorithm performance guava