为了账号安全,请及时绑定邮箱和手机立即绑定

java8 简化映射的转换

java8 简化映射的转换

蓝山帝景 2022-07-27 21:41:36
我有这个类结构: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 的引用,而不是它的 id(我无法更改),所以这就是为什么现在我需要创建一个 map,所以我的方法签名看起来像这样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 回答

?
开满天机

TA贡献1786条经验 获得超13个赞

如果调用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。


查看完整回答
反对 回复 2022-07-27
?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

也许只是直接迭代 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;

}


查看完整回答
反对 回复 2022-07-27
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

像这样的东西不会起作用吗?我没有编译器,所以我无法真正测试它


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

                                      )

                     );

}


查看完整回答
反对 回复 2022-07-27
  • 3 回答
  • 0 关注
  • 90 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信