java8 упрощает преобразования на карту - PullRequest
3 голосов
/ 10 марта 2019

У меня есть такая структура класса:

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());
}

Есть лиспособ сделать это проще ???

Ответы [ 3 ]

2 голосов
/ 11 марта 2019

Если вызов getCsByIds стоит дорого, ваша первоначальная идея вполне прилична для самореализации. Это может также быть сокращено к:

public Map<A, List<C>> convert(Collection<A> as) {
    List<Long> cIds = as.stream()
            .flatMap(a -> a.getBs().stream())
            .map(B::getIdOfC)
            .collect(Collectors.toList());
    Map<Long, C> csMap = getCsByIds(cIds).stream()
            .collect(Collectors.toMap(C::getId, Function.identity()));

    return as.stream()
            .collect(Collectors.toMap(Function.identity(),
                    a -> a.getBs().stream().map(b -> csMap.get(b.getIdOfC()))
                            .collect(Collectors.toList()), (a, b) -> b));
}

где вы можете выбрать функцию слияния (a,b) -> b соответственно.

1 голос
/ 11 марта 2019

Может быть, просто перебрать As напрямую? (компилятора нет, так что, возможно, фрагмент не готов к компиляции)

public Map<A, List<C>> convert(Collection<A> as) {
  Map<A, List<C>> result = new HashMap<>();
  for(A a: as){
     List<Long> cIds = a.getBs().stream()
                         .map(B::getIdOfC)
                         .collect(Collectors.toList());
     result.put(a, getCsByIds(cIds));
  }
  return result;
}
0 голосов
/ 11 марта 2019

Не будет ли что-то подобное этой работой?У меня нет компилятора, поэтому я не могу его протестировать

public Map<A, List<C>> convert(Collection<A> as) {
    return as.stream()
             .collect(Collectors.toMap(Function::identity,
                                       a -> a.getBs().stream()
                                                     .map(B::getIdOfC)
                                                     .flatMap(id -> getCsByIds(asList(id))
                                                                   .values()
                                                                   .stream())
                                                     .collect(Collectors.toList())
                                      )
                     );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...