Одним из возможных решений, предложенным в документе answer by Naman Gala, является использование Map
от идентификаторов к объектам и объединение слияния сущностей при их одинаковом идентификаторе.
Это реализуется здесь в методе 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]]
Что касается просьбы сделать это с лямбды: Это, наверное, можно написать какой-нибудь каверзный entities.stream().collect(...)
приложения. Но поскольку это не было главной целью вопроса, я оставлю эту часть ответа кому-то еще (но не пропущу этого небольшого намека: просто потому, что вы можете это не значит, что вам нужно. Иногда цикл просто отлично).
Также обратите внимание, что это можно легко обобщить, возможно, предоставив некоторые словарные базы из баз данных. Но я думаю, что на главный вопрос нужно ответить.
Как объединить текст, запрос и категорию? – m0skit0
Эти поля не будут объединены (они будут одинаковыми, только разница в категориях полей и триггерах). –