我有一个这样的对象
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())
答案 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);