我在多个客户端上同步数据时遇到问题。 为简单起见,假设我有两个可能重复的集合(名称是关键字):
"collection1": [
{
"name": "a",
"timestamp": 1
},
{
"name": "a",
"timestamp": 2
},
{
"name": "b",
"timestamp": 1
}]
"collection2": [
{
"name": "a",
"timestamp": 3
},
{
"name": "c",
"timestamp": 2
}]
我希望收集没有重复(名称是关键),具有最高的时间戳值。所以在合并之后它应该看起来像:
"collection3": [
{
"name": "b",
"timestamp": 1
},
{
"name": "a",
"timestamp": 3
},
{
"name": "c",
"timestamp": 2
}]
顺便说一下。我不关心订单。 我不能简单地说 Set = new HashSet<>(collectionn); 因为没有替换过载。
我的想法是做3次removeDuplication
使用此O(n ^ 2)removeDuplication函数:
LinkedList<MyObject> finalList = new LinkedList<>();
for (MyObject newObject : collection) {
boolean foundSimillar = false;
for (MyObject objectAlreadyAdded : finalList) {
if (Objects.equals(newObject, objectAlreadyAdded)) { // in this case if(name1 == name2)
foundSimillar = true;
long newObjectTime = newObject.lastTimeModified;
long alreadyAddedObjectTime = objectAlreadyAdded.lastTimeModified;
if (newObjectTime > alreadyAddedObjectTime) {
finalList.remove(objectAlreadyAdded);
finalList.add(newObject);
break;
}
}
}
if(!foundSimillar)
finalList.add(newObject);
}
是否有比3 * O(n ^ 2)更有效的算法?
答案 0 :(得分:4)
您应该可以使用地图执行此操作。您只需检查密钥是否在地图中(如果newValue&gt; oldValue则更新值),否则您将移动到下一个元素。
总时间复杂度应为O(N)
完成所有插入后,您可以通过一次迭代重建json。
答案 1 :(得分:2)
您可以在O(N)时间内使用标准流收集器:
Collection<Thing> merged =
Stream.of(collection1, collection2)
.flatMap(Collection::stream)
.collect(groupingBy(Thing::getName, Collectors.maxBy(Comparator.comparing(Thing::getTimestamp))))
.values()
.stream()
.map(Optional::get)
.collect(Collectors.toList());
答案 2 :(得分:1)
如果您使用的是Java 8并且已将值存储在地图中,那么如果您可以更新当前集合而不是创建新集合,则可以一步完成整个过程:
Map<String, Date> map1, map2;
map1.forEach((n, d) -> map2.merge(n, d, (d1, d2) -> d1.after(d2) ? d1 : d2));
Map.merge
是一种非常聪明的方法。如果它不存在,它会添加键和值。如果是,则应用给定的函数来确定要使用的值。非常适合你的情况。
如果你想要它在新地图中而不是旧地图中,那么:
Map<String, Date> map3 = new HashMap<>(map1);
map2.forEach((n, d) -> map3.merge(n, d, (v1, v2) -> v1.after(v2) ? v1 : v2));