У меня есть такая структура класса:
public class A {
private List<B> bs;
...//getters
}
public class C {
private Long id;
...//getters
}
public class B {
private Long idOfC;
...//more stuff
}
B :: getIdOfC соответствует C :: getId
В лучшем дизайне B будет содержать ссылку на C, ачем его идентификатор (я не могу это изменить), поэтому сейчас мне нужно создать карту , поэтому сигнатура моего метода выглядит следующим образом
public Map<A, List<C>> convert(Collection<A> collection)
Внутри этого метода преобразования есть
List<C> getCsByIds(List<Long> id)
, который позже используется для сравнения его с B.idOfC, но этот метод должен быть только один, так как он довольно дорогой.
Так что если я пойду так:
List<B> bs = Arrays.asList(new B(10L), new B(11L)); //10L and 11L are the values of idOfC
List<A> as = Arrays.asList(bs);
//And assuming getCsByIds returns Arrays.asList(new C(10L), new C(11L), new C(12L));
затем
Map<A, List<C>> map = convert(as);
map.values().get(0)
возвращает что-то вроде Arrays.asList(new C(10L), new C(11L))
Метод, который делает это довольно массивным, на мой взгляд:
public Map<A, List<C>> convert(Collection<A> as) {
List<Long> cIds = as.stream()
.flatMap(a -> a.getBs().stream())
.map(B::getCId)
.collect(Collectors.toList());
//single call to gsCsByIds
Map<Long, C> csMap = getCsByIds(cIds)
.stream()
.collect(Collectors.toMap(C::getId, Function.identity()));
//a whole new map is created by iterating over the list called "as"
Map<A, List<C>> csByAs = new HashMap<>();
if (!csMap.isEmpty()) {
for (A a : as) {
Set<C> cs = getCsFromMap(csMap, a.getBs());
if (!cs.isEmpty()) {
csByAs.put(a, new ArrayList<>(cs));
}
}
}
return csByAs;
}
private Set<B> getCsFromMap(Map<Long, C> cMap, List<B> bs) {
return bs.stream()
.map(b -> cMap.get(b.getIdOfc()))
.collect(Collectors.toSet());
}
Есть лиспособ сделать это проще ???