Java 8流filter – 基于排序的pdate
我试图在filter中对字段进行排序。
输入文件/样本记录:
DocumentList: [ Document{ { _id=5975ff00a213745b5e1a8ed9, u_id=, mailboxcontent_id=5975ff00a213745b5e1a8ed8, idmapping=Document{ {ptype=PDF, cid=00988, normalizedcid=00988, systeminstanceid=, sourceschemaname=, pid=0244810006} }, batchid=null, pdate=Tue Jul 11 17:52:25 IST 2017, locale=en_US } }, Document{ { _id=597608aba213742554f537a6, u_id=, mailboxcontent_id=597608aba213742554f537a3, idmapping=Document{ {platformtype=PDF, cid=00999, normalizedcid=00999, systeminstanceid=, sourceschemaname=, pid=0244810006} }, batchid=null, pdate=Fri Jul 28 01:26:22 IST 2017, locale=en_US } } ]
在这里,我需要基于pdate进行排序。
List outList = documentList.stream() .filter(p -> p.getInteger(CommonConstants.VISIBILITY) == 1) .parallel() .sequential() .collect(Collectors.toCollection(ArrayList::new)) .sort() .skip(skipValue) .limit(limtValue);
不知道如何排序
"order by pdate DESC"
先感谢您!
您可以使用.sorted()
Stream API方法:
.sorted(Comparator.comparing(Document::getPDate).reversed())
完整的,重构的例子:
List outList = documentList.stream() .filter(p -> p.getInteger(CommonConstants.VISIBILITY) == 1) .sorted(Comparator.comparing(Document::getPDate).reversed()) .skip(skipValue).limit(limtValue) .collect(Collectors.toCollection(ArrayList::new))
几件事要记住:
- 如果您不关心
List
实现,请使用Collectors.toList()
-
collect()
是一个终端操作,应该作为最后一个操作调用 -
.parallel().sequential()
这完全没用 – 如果你想并行化,坚持.parallel()
如果没有,不要写任何东西,默认情况.parallel()
顺序 - 为了排序,整个Stream将被加载到内存中
对于pivovarit的回答的替代方法,如果您的数据集可能太大而无法一次保留在内存中,这可能很有用(已排序的Stream
必须在中间容器中维护整个底层数据集以提供正确排序的能力)。
我们不会在这里使用流排序操作:相反,我们将使用数据结构来保存我们告诉它的集合中的多个元素,并将根据排序标准推出额外的元素(我不声称在这里提供最佳实现,只是它的想法)。
为此,我们需要定制收集器:
class SortedPileCollector implements Collector, List > { int maxSize; Comparator comptr; public SortedPileCollector(int maxSize, Comparator comparator) { if (maxSize < 1) { throw new IllegalArgumentException("Max size cannot be " + maxSize); } this.maxSize = maxSize; comptr = Objects.requireNonNull(comparator); } public Supplier> supplier() { return () -> new TreeSet<>(comptr); } public BiConsumer, E> accumulator() { return this::accumulate; // see below } public BinaryOperator> combiner() { return this::combine; } public Function, List > finisher() { return set -> new ArrayList<>(set); } public Set characteristics() { return EnumSet.of(Characteristics.UNORDERED); } // The interesting part public void accumulate(SortedSet set, E el) { Objects.requireNonNull(el); Objects.requireNonNull(set); if (set.size() < maxSize) { set.add(el); } else { if (set.contains(el)) { return; // we already have this element } E tailEl = set.last(); Comparator c = set.comparator(); if (c.compare(tailEl, el) <= 0) { // If we did not have capacity, received element would've gone to the end of our set. // However, since we are at capacity, we will skip the element return; } else { // We received element that we should preserve. // Remove set tail and add our new element. set.remove(tailEl); set.add(el); } } } public SortedSet combine(SortedSet first, SortedSet second) { SortedSet result = new TreeSet<>(first); second.forEach(el -> accumulate(result, el)); // inefficient, but hopefully you see the general idea. return result; } }
上面的收集器充当管理有序数据集的可变结构。 请注意,此实现会忽略“重复”元素 – 如果要允许重复,则需要更改实现。
假设您需要三个顶级元素,请将此比较器用于您的情况:
Comparator comparator = Comparator.comparing(Document::getPDate).reversed(); // see pivovarit's answer List = documentList.stream() .filter(p -> p.getInteger(VISIBILITY) == 1) .collect(new SortedPileCollector<>(3, comparator));
获得结果列表后,请执行此操作,假设Document.getPDate()
返回pDate
Collections.sort(outList, Comparator.comparing(Document::getPDate).reversed());