Stream 2 loops using java 8 and return outer loop object from inner loop

Men*_*ini 1 java loops for-loop java-8 java-stream

I have a function like this:

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;
}
Run Code Online (Sandbox Code Playgroud)

I wanted to change the code by using java 8 streams. Is it possible because I am returning property from 1st loop inside the 2nd loop.

I tried these 2 ways. But its of no help and seems wrong:

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;
}
Run Code Online (Sandbox Code Playgroud)

I tried this , but I don’t think I can collect the value that I need

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*/);
Run Code Online (Sandbox Code Playgroud)

Is using stream bad idea for my requirement? Or am I on the wrong path?

lcz*_*ski 5

Try something like this:

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);
Run Code Online (Sandbox Code Playgroud)

UPDATE

Holger mention in comment that it would be good to replace flatMap with filter so here is newer version:

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);
Run Code Online (Sandbox Code Playgroud)

  • 代替`flatMap`步骤,使用`.filter(r-&gt; r.getB()。stream().anyMatch(c-&gt; c &amp;&amp;((C)c).getV( )instanceof V)).map(R :: getXyz)` (3认同)