如何使用 Java 8 lambda 从流中获取一系列项目? [英] How to get a range of items from stream using Java 8 lambda?

查看:19
本文介绍了如何使用 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....

为此,您必须在我的答案中使用与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.

获得计数后,您可以根据所需的计数和百分比计算 skiplimit 的正确值.像这样的事情可能会奏效:

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

当然,您必须对 fromto 进行错误检查.一个更微妙的问题是确定要发射多少个元素.例如,如果您有十个元素,它们位于索引 [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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆