如何通过分组按LawInfoType在所有游戏中按日期查找最大LawInfo?

我有一个简单的模型:

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;
}


主要测试

 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)); //!!!????


但我需要按日期按游戏逐个分组

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


small-> [LawInfo(橄榄球,最大日期),LawInfo(hokey,最大日期),LawInfo(高尔夫,最大日期),LawInfo(篮球,最大日期)]

middle-> [LawInfo(橄榄球,最大日期),LawInfo(hokey,最大日期),LawInfo(高尔夫,最大日期),LawInfo(篮球,最大日期)]

big-> [LawInfo(橄榄球,最大日期),LawInfo(hokey,最大日期),LawInfo(高尔夫,最大日期),LawInfo(篮球,最大日期)]

最佳答案

您可以使用

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()));
});


将打印

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


与您的测试数据。请注意,该范围内的日期值不太适合进行一致性检查,因为此数据集的其他日期在打印输出中看起来像是具有较高的数字,因为年份不是以这种格式打印为带符号的数字。我建议生成具有合理值的日期,例如具有四位数的正数年…

09-05 19:59