【问题标题】:Stream 2 loops using java 8 and return outer loop object from inner loop流 2 循环使用 java 8 并从内循环返回外循环对象
【发布时间】:2020-02-25 15:11:23
【问题描述】:

我有这样的功能:

public static Xyz getXyz(P p) {
    if (p == null) {
        return null;
    }

    List<Object> bs = p.getB();
    if (CollectionUtils.isEmpty(Bs)) {
        return null;
    }
    for (Object b : bs) {
        if (b instanceof R) {
            R r = (R) b;
            List<Object> cObjects = r.getB();
            for (Object cObject : cObjects) {
                if (cObject instanceof C) {
                    C c = (C) cObject;
                    Object vObject = cObject.getV();
                    if (vObject instanceof V) {
                        return r.getXyz();
                    }
                }
            }
        }
    }
    return null;
}

我想通过使用 java 8 流来更改代码。 是否有可能,因为我从第二个循环内的第一个循环返回属性。

我尝试了这两种方法。但它没有任何帮助,而且似乎是错误的:

public static Xyz getXyz(P p) {
    if (p == null) {
        return null;
    }

    List<Object> bs = p.getB();
    if (CollectionUtils.isEmpty(Bs)) {
        return null;
    }

       Xyz xyz = null;
         bs.stream()
            .filter(b -> (b instanceof R))
            .map(b -> (R) b).forEach(r -> {
                    List<Object> cObjects = = r.getB();
                     Optional vOptional= cObjects.stream()
                        .filter(cObjects -> (cObjects instanceof C))
                        .map(cObjects -> ((C) cObjects).getV())
                        .filter(vObject -> (vObject instanceof V)).findFirst();
                     if(vOptional.isPresent()){
                         xyz =  r.getXyz();
                         return;
                     }
    });
        return xyz;
}

我试过这个,但我认为我不能收集到我需要的值

bs.stream()
    .filter(b -> (b instanceof R))
    .flatMap(b -> ((R) b).getB().stream())
    .filter(cObject -> (cObject instanceof C))
    .map(cObject -> ((C) cObject).getV())
    .filter(vObject -> (vObject instanceof V))
    .collect(/*no idea if I can collect the value I desire*/);

对我的要求使用流是个坏主意吗?还是我走错了路?

【问题讨论】:

  • 重新考虑instanceof 所需的那些检查以及之后的显式转换,它们是您正在查看的复杂性的根源。
  • 所以你基本上有一个 P 的实例,它包含一个可能是 R 实例的对象列表,如果任何这样的实例有一个 C 有一个 V 你想要返回RXyz? - 这意味着您将过滤R,然后映射到R,然后过滤R.b 以获得C.V,最后收集R.xyz。 - 听起来很复杂?好吧,这是你的代码 ;) - 对于所有这些神秘的名称,很难推理,特别是因为看起来好像那些 PR 实例可以包含任何类型的列表(那些 List&lt;Object&gt; bs = p.getB(); 等)。这真的有必要吗?
  • 不需要收集。由于您要返回第一个匹配项目,因此只需使用您已经证明知道的findFirst()。不要使用forEach
  • @Naman 的实例是必需的。无法避免。
  • @Thomas。是的..需要。抱歉命名约定。

标签: java loops for-loop java-8 java-stream


【解决方案1】:

试试这样的:

return bs.stream()
        .filter( b -> b instanceof R)
        .map(b -> (R) b)
        .flatMap(r -> r.getB().stream()
                .filter(cObject -> cObject instanceof C)
                .map(cObject -> ((C) cObject).getV())
                .filter(vObject -> vObject instanceof V)
                .map(v -> r.getXyz())
        ).findFirst().orElse(null);

更新

Holger 在评论中提到用filter 替换flatMap 会很好,所以这里是更新的版本:

return bs.stream()
        .filter(b -> b instanceof R)
        .map(b -> (R) b)
        .filter(r -> r.getB()
                .stream()
                .anyMatch(c -> c instanceof C && ((C) c).getV() instanceof V)
        )
        .map(R::getXyz)
        .findFirst().orElse(null);

【讨论】:

  • 代替flatMap这一步,使用.filter(r -&gt; r.getB().stream() .anyMatch(c -&gt; c instanceof C &amp;&amp; ((C)c).getV() instanceof V)) .map(R::getXyz)会更自然
猜你喜欢
  • 2018-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 2016-12-31
  • 2017-04-01
相关资源
最近更新 更多