在java 8中限制并获得平面列表

时间:2018-05-23 13:22:15

标签: java-8

我有一个这样的对象

public class Keyword
{
  private int id;
  private DateTime creationDate
  private int subjectId
  ...
}

所以现在我有像bellow

这样的数据列表

KeywordList = [{1,'2018-10-20',10},{1,'2018-10-21',10},{1,'2018-10-22 '10},{1, '2018年10月23日',20},{1, '2018年10月24日',20} {1, '2018年10月25日',20},{1,' 2018年10月26' 日,30},{1, '2018年10月27日',30},{1, '2018年10月28日',40}]

我想将此列表限制为主题ID

例如:如果我提供限制为2,它应该只包含每个主题ID的最新2条记录,方法是按creationDate排序并将结果作为列表返回。

resultList = KeywordList = [{1,'2018-10-21',10},{1,'2018-10-22',10},{1,'2018-10 -24' ,20},{1, '2018年10月25日',20},{1, '2018年10月26日',30},{1, '2018年10月27日',30},{ 1, '2018年10月28日',40}]

我们如何在Java 8中实现这种功能 我已经以这种方式实现了它。但我对这段代码表示怀疑。

dataList.stream()
        .collect(Collectors.groupingBy(Keyword::getSubjectId,
            Collectors.collectingAndThen(Collectors.toList(),
                myList-> myList.stream().sorted(Comparator.comparing(Keyword::getCreationDate).reversed()).limit(limit)
                    .collect(Collectors.toList()))))
        .values().stream().flatMap(List::stream).collect(Collectors.toList())

2 个答案:

答案 0 :(得分:5)

嗯,你可以分两步完成(假设DateTime具有可比性):

    yourInitialList
            .stream()
            .collect(Collectors.groupingBy(Keyword::getSubjectId));

    List<Keyword> result = map.values()
            .stream()
            .flatMap(x -> x.stream()
                          .sorted(Comparator.comparing(Keyword::getCreationDate))
                          .limit(2))
            .collect(Collectors.toList());

我认为这只能用Collectors.collectingAndThen一步完成,但不确定它的可读性。

答案 1 :(得分:0)

private static final Comparator<Keyword> COMPARE_BY_CREATION_DATE_DESC = (k1, k2) -> k2.getCreationDate().compareTo(k1.getCreationDate());

private static <T> Collector<T, ?, List<T>> limitingList(int limit) {
    return Collector.of(ArrayList::new,
            (l, e) -> {
                if (l.size() < limit)
                    l.add(e);
            },
            (l1, l2) -> {
                l1.addAll(l2.subList(0, Math.min(l2.size(), Math.max(0, limit - l1.size()))));
                return l1;
            }
    );
}

public static <R> Map<R, List<Keyword>> retrieveLast(List<Keyword> keywords, Function<Keyword, ? extends R> classifier, int limit) {
    return keywords.stream()
                   .sorted(COMPARE_BY_CREATION_DATE_DESC)
                   .collect(Collectors.groupingBy(classifier, limitingList(limit)));
}

客户的代码:

List<Keyword> keywords = Collections.emptyList();
Map<Integer, List<Keyword>> map = retrieveLast(keywords, Keyword::getSubjectId, 2);