简体   繁体   中英

Java 8 stream groupingBy. How to set field if only one object of grouping value?

I have Class

public class SomeClass {

    private String date;
    private int players;
    private int currency;

// getters setters omitted for brevity
}

I have collection of this objects. Now I want to group by date this objects and sum players count and set currencyId to 0. I do it by this way:

list = list.stream()
           .collect(
                    groupingBy(SomeClass::getDate,
                              collectingAndThen(reducing((a, b) -> {
                                  a.setDate(a.getDate());
                                  a.setPlayers(a.getPlayers() + b.getPlayers());
                                  a.setCurrency(0);
                                  return a;
                              }), Optional::get)))
           .values();

Every thing is fine except when I have only one object of certain date. That object doesnt set currency to 0 (because reducing don`t work if object is only one.) So this is my problem.

If I have:

   Object1 ("11.09", 12, 12)
   Object2 ("11.09", 8, 13)
   Object3 ("12.09", 1, 2)
   Object4 ("12.09", 0, 1)
   Object5 ("13.09", 12, 12)

The output must be:

   Object6 ("11.09", 20, 0)
   Object7 ("12.09", 1, 0)
   Object8 ("13.09", 12, **0**)

But instead:

   Object6 ("11.09", 20, 0)
   Object7 ("12.09", 1, 0)
   Object8 ("13.09", 12, **12**)

Help pls

Currency is not getting set to 0 as reducing will not be evaluated for single sigle result. If you want to set all currency to 0, map it 0 as below,

list.stream().map(ele->{ele.setCurrency(0);return ele;}).collect(
        groupingBy(SomeClass::getDate,
                collectingAndThen(reducing((a, b) -> {
                    a.setPlayers(a.getPlayers() + b.getPlayers());
                    return a;
                }), Optional::get)))
        .values();

As correctly pointed by @Holger, you may want to use toMap ,

list.stream()
    .map(ele->{ele.setCurrency(0);return ele;})
    .collect(toMap(SomeClass::getDate, Function.identity(), (a, b) -> {
        a.setPlayers(a.getPlayers() + b.getPlayers());
        return a;
    })).values();

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM