如何使用Java 8 Lambda从流中获取一系列项目? [英] How to get a range of items from stream using Java 8 lambda?
问题描述
在先前的问题中[如何在Java 8中动态进行过滤?] Stuart Marks给出了一个很好的答案,并提供了一些有用的实用程序来处理从流中选择topN和topPercent.
In a previous question [ How to dynamically do filtering in Java 8? ] Stuart Marks gave a wonderful answer, and provided several useful utilities to handle selection of topN and topPercent from stream.
我将从他的原始答案中将其包括在这里:
I'll include them here from his original answer :
@FunctionalInterface
public interface Criterion {
Stream<Widget> apply(Stream<Widget> s);
}
Criterion topN(Comparator<Widget> cmp, long n) {
return stream -> stream.sorted(cmp).limit(n);
}
Criterion topPercent(Comparator<Widget> cmp, double pct) {
return stream -> {
List<Widget> temp =
stream.sorted(cmp).collect(toList());
return temp.stream()
.limit((long)(temp.size() * pct));
};
}
我的问题是:
[1]如何从具有一定数量项的流中从3到7中获得热门项,因此,如果流中有来自A1,A2 .... A10的项,则调用
[1] How to get top items from 3 to 7 from a stream with certain amount of items, so if the stream has items from A1, A2 .. A10, the call to
topNFromRange(Comparator<Widget> cmp, long from, long to) = topNFromRange(comparing(Widget::length), 3L, 7L)
将返回{A3,A4,A5,A6,A7}
will return { A3, A4, A5, A6, A7 }
我想到的最简单的方法是从原始文件中获取前7个[T7],从原始文件中获取前3个[T3],然后获取T7-T3.
The simplest way I can think of is get the top 7 [ T7 ] from original, get the top 3 [ T3 ] from original, and then get T7 - T3.
[2]如何从具有一定数量的项目的流中获取前10%到前30%的顶部项目,因此,如果流中有X1,X2 .... X100中的项目,则调用
[2] How to get top items from top 10% to top 30% from a stream with certain amount of items, so if the stream has items from X1, X2 .. X100, the call to
topPercentFromRange(Comparator<Widget> cmp, double from, double to) = topNFromRange(comparing(Widget::length), 0.10, 0.30)
将返回{X10,X11,X12,...,X29,X30}
will return { X10, X11, X12, ..., X29, X30 }
我能想到的最简单的方法是从原始文件中获取前30%的[TP30],从原始文件中获取前10%的[TP10],然后获取TP30-TP10.
The simplest way I can think of is get the top 30% [ TP30 ] from original, get the top 10% [ TP10 ] from original, and then get TP30 - TP10.
使用Java 8 Lambda简洁表达上述情况的更好方法有哪些?
What are some better ways to use Java 8 Lambda to concisely express the above situations ?
推荐答案
用户skiwi已经已回答第一部分问题.第二部分是:
User skiwi already answered the first part of the question. The second part is:
(2)如何从具有一定项目量的信息流中将前10%到前30%的顶级项目获取....
(2) How to get top items from top 10% to top 30% from a stream with certain amount of items....
为此,您必须在我对另一个问题的 answer 中使用与topPercent
类似的技术.也就是说,您必须将元素收集到列表中,以便可能在完成一些上游过滤之后获得元素的计数.
To do this, you have to use a similar technique as topPercent
in my answer to the other question. That is, you have to collect the elements into a list in order to be able to get a count of the elements, possibly after some upstream filtering has been done.
一旦有了计数,就可以根据计数和所需的百分比为skip
和limit
计算正确的值.这样的事情可能会起作用:
Once you have the count, then you compute the right values for skip
and limit
based on the count and the percentages you want. Something like this might work:
Criterion topPercentFromRange(Comparator<Widget> cmp, double from, double to) {
return stream -> {
List<Widget> temp =
stream.sorted(cmp).collect(toList());
return temp.stream()
.skip((long)(temp.size() * from))
.limit((long)(temp.size() * (to - from)));
};
}
当然,您必须对from
和to
进行错误检查.一个更微妙的问题是确定要发射多少个元素.例如,如果您有十个元素,则它们的索引为[0..9],分别对应于0%,10%,20%,...,90%.但是,如果您要求的范围是9%到11%,则上面的代码将根本不发出任何元素,而不像您期望的那样发出10%的元素.因此,可能需要对百分比计算进行一些修改,以适应您要尝试执行的操作的语义.
Of course you will have to do error checking on from
and to
. A more subtle problem is determining how many elements to emit. For example, if you have ten elements, they are at indexes [0..9], which correspond to 0%, 10%, 20%, ..., 90%. But if you were to ask for a range from 9% to 11%, the above code would emit no elements at all, not the one at 10% like you might expect. So some tinkering with the percentage computations is probably necessary to fit the semantics of what you're trying to do.
这篇关于如何使用Java 8 Lambda从流中获取一系列项目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!