java 8 stream how to groupingBy in result grouping

2019-06-05 23:41发布

how to find max LawInfo by date fo all games in groupingBy LawInfoType?

i have simple model :

public enum Game {
    football,
    hokey,
    golf,
    basketball
}

public class LawInfo {
    private Date minDate;
    private State state;
    private LawInfoType textType;
    private String lawInfoText;
    private Game game;
}

public enum LawInfoType {
     big, middle , small;
}

public enum State {
    draft, ready, cancel;
}

main test

 List<LawInfo> list = new ArrayList<>();

        LawInfo info = null;
        Random random = new Random(123);
        for (int i = 0; i < 3; i++) {

            for (State state : State.values()) {
                for (LawInfoType lawInfoType : LawInfoType.values()) {
                    for (Game game : Game.values()) {
                        info = new LawInfo(new Date(random.nextLong()), state, lawInfoType, "TEXT", game);
                        list.add(info);
                    }

                }
            }
        }

        Predicate<LawInfo>  isReady = l->l.getState().equals(State.ready);


  Map<LawInfoType, List<LawInfo>> map0 = list.stream()
                .filter(isReady)
                .collect(groupingBy(LawInfo::getTextType)); //!!!????

but I need to get in each group max by date group by games

like this : Map<LawInfoType, List<LawInfo>> 

small->[LawInfo(football, max date),LawInfo(hokey, max date) ,LawInfo(golf, max date) , LawInfo(basketball, max date)]

middle->[LawInfo(football, max date),LawInfo(hokey, max date) ,LawInfo(golf, max date) , LawInfo(basketball, max date)]

big->[LawInfo(football, max date),LawInfo(hokey, max date) ,LawInfo(golf, max date) , LawInfo(basketball, max date)]

2条回答
趁早两清
2楼-- · 2019-06-05 23:59

You could group by two properties (getTextType and getGame), and a max collector.

Something like this:

Map<LawInfoType, Map<Game, Optional<LawInfo>>> map0 = list.stream().collect(
    Collectors.groupingBy(LawInfo::getTextType,
         Collectors.groupingBy(LawInfo::getGame,           
              Collectors.maxBy(Comparator.comparing(LawInfo::getMinDate))
    )));
查看更多
劳资没心,怎么记你
3楼-- · 2019-06-06 00:04

You can use

Map<LawInfoType, List<LawInfo>> result = list.stream()
    .filter(l -> l.getState()==State.ready)
    .collect(
        Collectors.groupingBy(LawInfo::getTextType,
            Collectors.collectingAndThen(
                Collectors.groupingBy(LawInfo::getGame,
                    Collectors.maxBy(Comparator.comparing(LawInfo::getMinDate))),
                m -> m.values().stream().map(Optional::get).collect(Collectors.toList())
        )));

result.forEach((k,v) -> {
    System.out.println(k);
    v.forEach(l -> System.out.printf("%14s, %15tF%n", l.getGame(), l.getMinDate()));
});

which will print

big
          golf, 250345012-06-20
    basketball,  53051589-05-19
      football, 177220545-11-30
         hokey, 277009605-05-01
middle
          golf,  24379695-11-03
    basketball, 283700233-08-25
      football, 248125707-04-08
         hokey, 195919793-04-22
small
          golf, 152237339-07-10
    basketball, 269880024-08-24
      football, 285393288-11-14
         hokey, 276036745-09-23

with your test data. Note that date values in that range are not quite suitable for consistency checks as other dates of this data set may look like having a higher number in printouts because the year is not printed as signed number with this format. I’d recommend to generate dates with reasonable values, e.g. having four digit positive number years…

查看更多
登录 后发表回答