如answer by Naman Gala 中所建议的,一种可能的解决方案是使用Map 从ID 到实体,并在实体具有相同ID 时手动合并实体。
这是在mergeById 方法中实现的,其中有一些虚拟/示例输入
- 必须合并两个实体(由于 ID 相同)
- 两个实体相等(它们也将被“合并”,产生与其中一个输入相同的结果)
.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
public class MergeById
{
public static void main(String[] args)
{
List<Entity> entities = new ArrayList<Entity>();
entities.add(new Entity("0", "A", "X", "-1",
Arrays.asList("C0", "C1"), Arrays.asList("T0", "T1")));
entities.add(new Entity("0", "A", "X", "-1",
Arrays.asList("C2", "C3"), Arrays.asList("T2")));
entities.add(new Entity("1", "B", "Y", "-2",
Arrays.asList("C0"), Arrays.asList("T0", "T1")));
entities.add(new Entity("1", "B", "Y", "-2",
Arrays.asList("C0"), Arrays.asList("T0", "T1")));
entities.add(new Entity("2", "C", "Z", "-3",
Arrays.asList("C0", "C1"), Arrays.asList("T1")));
System.out.println("Before merge:");
for (Entity entity : entities)
{
System.out.println(entity);
}
List<Entity> merged = mergeById(entities);
System.out.println("After merge:");
for (Entity entity : merged)
{
System.out.println(entity);
}
}
private static List<Entity> mergeById(Iterable<? extends Entity> entities)
{
Map<String, Entity> merged = new HashMap<String, Entity>();
for (Entity entity : entities)
{
String id = entity.getId();
Entity present = merged.get(id);
if (present == null)
{
merged.put(id, entity);
}
else
{
merged.put(id, Entity.merge(present, entity));
}
}
return new ArrayList<Entity>(merged.values());
}
}
class Entity
{
private String id;
private String text;
private String query;
private String locatorId;
private Collection<String> categories;
private Collection<String> triggers;
Entity()
{
categories = new LinkedHashSet<String>();
triggers = new LinkedHashSet<String>();
}
Entity(String id, String text, String query, String locatorId,
Collection<String> categories, Collection<String> triggers)
{
this.id = id;
this.text = text;
this.query = query;
this.locatorId = locatorId;
this.categories = categories;
this.triggers = triggers;
}
String getId()
{
return id;
}
static Entity merge(Entity e0, Entity e1)
{
if (!Objects.equals(e0.id, e1.id))
{
throw new IllegalArgumentException("Different id");
}
if (!Objects.equals(e0.text, e1.text))
{
throw new IllegalArgumentException("Different text");
}
if (!Objects.equals(e0.query, e1.query))
{
throw new IllegalArgumentException("Different query");
}
if (!Objects.equals(e0.locatorId, e1.locatorId))
{
throw new IllegalArgumentException("Different id");
}
Entity e = new Entity(e0.id, e0.text, e0.query, e0.locatorId,
new LinkedHashSet<String>(), new LinkedHashSet<String>());
e.categories.addAll(e0.categories);
e.categories.addAll(e1.categories);
e.triggers.addAll(e0.triggers);
e.triggers.addAll(e1.triggers);
return e;
}
@Override
public String toString()
{
return "Entity [id=" + id + ", text=" + text + ", query=" + query +
", locatorId=" + locatorId + ", categories=" + categories +
", triggers=" + triggers + "]";
}
}
输出是
Before merge:
Entity [id=0, text=A, query=X, locatorId=-1, categories=[C0, C1], triggers=[T0, T1]]
Entity [id=0, text=A, query=X, locatorId=-1, categories=[C2, C3], triggers=[T2]]
Entity [id=1, text=B, query=Y, locatorId=-2, categories=[C0], triggers=[T0, T1]]
Entity [id=1, text=B, query=Y, locatorId=-2, categories=[C0], triggers=[T0, T1]]
Entity [id=2, text=C, query=Z, locatorId=-3, categories=[C0, C1], triggers=[T1]]
After merge:
Entity [id=0, text=A, query=X, locatorId=-1, categories=[C0, C1, C2, C3], triggers=[T0, T1, T2]]
Entity [id=1, text=B, query=Y, locatorId=-2, categories=[C0], triggers=[T0, T1]]
Entity [id=2, text=C, query=Z, locatorId=-3, categories=[C0, C1], triggers=[T1]]
关于使用 lambdas 执行此操作的请求:可能会编写一些棘手的 entities.stream().collect(...) 应用程序。但由于这不是问题的主要目标,我将把这部分答案留给其他人(但不会省略这个小提示:仅仅因为你可以并不意味着你必须这样做。有时,一个循环很好)。
还请注意,这很容易概括,可能会从数据库中借用一些词汇。但我认为应该回答问题的要点。