mounaim
mounaim

Reputation: 1180

Applying a predicate with anyMatch() on a map keyset stream and returning some result when the predicate is false

I have a class Parcelle with three attributes num and nature and autre_nature. and a list of Parcelle listParcelles. I am experiencing with Java 8 Streams, and what I would like to achieve is to group by num and return the Parcelle which has both non null nature and autre_nature attributes, otherwise just return one Parcelle from the group at random.

Example :   
Input:   

    ligneParcelles[[num=1,nature=TC,autre_nature=TCC],  
                   [num=1,nature=TC,autre_nature=null],
                   [num=2,nature=TC,autre_nature=null],
                   [num=3,nature=TC,autre_nature=null],
                   [num=3,nature=Alpha,autre_nature=null],
                   [num=4,nature=TC,autre_nature=TC]
                   [num=4,nature=TC,autre_nature=null]]
Output :   
    ligneParcelles [[num=1,nature=TC,autre_nature=TCC],  
                   [num=2,nature=TC,autre_nature=null],
                   [num=3,nature=Alpha,autre_nature=null],
                   [num=4,nature=TC,autre_nature=TC]]

for grouping I used the following code :

Map<String, List<Parcelle>> mapLignesParcelles = listParcelles.stream()                                                    

          .collect(Collectors.groupingBy(lp->lp.getNum()+""));  

but I am not sure what to use in order to get the final result, I can stream mapLignesParcelles keyset and I think of anymatch with a predicate lp.getNature()!=null && lp.getAutre_Nature() !=null but How can I express the fact to return any element when the predicate does not hold ?

Upvotes: 3

Views: 2336

Answers (2)

Naman
Naman

Reputation: 31878

You seem to be looking for a mapping of each Num to a single Parcelle in the form of Map<String, Parcelle> instead of a List as in groupingBy. One way is to use toMap while collecting as:

Map<String, Parcelle> output = listParcelles.stream()
        .collect(Collectors.toMap(a -> a.getNum() + "", a -> a,
                (parcelle1, parcelle2) -> parcelle1.getNature() != null
                        && parcelle1.getAutre_nature() != null ? parcelle1 : parcelle2));

Another from the way ahead of grouping could be as:

Map<String, Parcelle> output = mapLignesParcelles.entrySet().stream()
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), e.getValue()
                .stream()
                .filter(lp -> lp.getNature() != null && lp.getAutre_nature() != null)
                .findAny()
                .orElse(e.getValue().get(new Random().nextInt(e.getValue().size())))))
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Upvotes: 3

Andrew
Andrew

Reputation: 49606

stream
    .filter(yourCondition)
    .findFirst()
    .orElse(randomlySelectedObject);

You have a stream, you filter it by your condition, you try to get the first element that matches the criterion, you return it if found, otherwise you return randomlySelectedObject.

Upvotes: 2

Related Questions