Java 是否可以使用Streams.intRange功能?
我想使用Streams.intRange(int start,int end,int step)来实现逆序流。然而,java.util.Streams类似乎不再可用(但它仍然在标准库的rt.jar中)。这个方法是在其他类中还是被其他类所取代?JDK中确实不再有这样的方法了;您可以得到的下一个最接近的是Java 是否可以使用Streams.intRange功能?,java,java-8,java-stream,Java,Java 8,Java Stream,我想使用Streams.intRange(int start,int end,int step)来实现逆序流。然而,java.util.Streams类似乎不再可用(但它仍然在标准库的rt.jar中)。这个方法是在其他类中还是被其他类所取代?JDK中确实不再有这样的方法了;您可以得到的下一个最接近的是IntStream.range()但这只会一步一步地进行 这里的一个解决方案是实现您自己的拆分器;例如,类似这样的东西(非常粗糙;可以改进!): 然后,您将使用从上述类的实例生成流。JDK中确实不再
IntStream.range()
但这只会一步一步地进行
这里的一个解决方案是实现您自己的拆分器;例如,类似这样的东西(非常粗糙;可以改进!):
然后,您将使用从上述类的实例生成流。JDK中确实不再有这样的方法;下一个最接近的方法是IntStream.range()
,但这只会一步一步地进行
这里的一个解决方案是实现您自己的拆分器;例如,类似这样的东西(非常粗糙;可以改进!):
然后,您将使用从上述类的实例生成流。您可以基于无限流创建流:
public static IntStream intRange(int start, int end, int step ) {
if ( step == 0 ) {
throw new IllegalArgumentException("Cannot iterate with a step of zero");
}
final int limit = (end - start + step) / step;
if ( limit < 0 ) {
return IntStream.empty();
}
return IntStream.iterate(start, x -> x + step )
.limit( limit );
}
可能的用途:
intRange(8 ,2, -2).forEach(System.out::println);
输出:
8
6
4
2
您可以基于无限流创建它:
public static IntStream intRange(int start, int end, int step ) {
if ( step == 0 ) {
throw new IllegalArgumentException("Cannot iterate with a step of zero");
}
final int limit = (end - start + step) / step;
if ( limit < 0 ) {
return IntStream.empty();
}
return IntStream.iterate(start, x -> x + step )
.limit( limit );
}
可能的用途:
intRange(8 ,2, -2).forEach(System.out::println);
输出:
8
6
4
2
目前提出的两种解决方案都不考虑并行化。@fge提出的拆分器根本不并行。@realponsum提出的基于迭代的流将使用缓冲并行化(一些数字将被加载到中间数组并交给另一个线程),这并不总是有效的
有一个非常简单的替代解决方案,它提供了正常的并行化(这里end
是专用的):
或者,如果您想考虑非常奇怪的输入,如内部消息(Integer.MAX\u值、Integer.MIN\u值、Integer.MIN\u值)
:
目前提出的两种解决方案都不考虑并行化。@fge提出的拆分器根本不并行。@realponsum提出的基于迭代的流将使用缓冲并行化(一些数字将被加载到中间数组并交给另一个线程),这并不总是有效的
有一个非常简单的替代解决方案,它提供了正常的并行化(这里end
是专用的):
或者,如果您想考虑非常奇怪的输入,如内部消息(Integer.MAX\u值、Integer.MIN\u值、Integer.MIN\u值)
:
此链接可能对您的需求有所帮助:http://stackoverflow.com/questions/24010109/java-8-stream-reverse-order
此链接可能对您的需求有所帮助:http://stackoverflow.com/questions/24010109/java-8-stream-reverse-order
足够近。很遗憾,此功能已被删除。距离足够近。遗憾的是,此函数已被删除。舍入误差太大,例如,intRange(0,9,2).forEach(System.out::println)代码>不会打印8
。除此之外,此解决方案也是唯一一个具有可预测大小的解决方案,它在内部甚至在顺序操作中使用,例如toArray()
。要想出一个对两个方向都有效的限制
计算并不容易。到目前为止,我得到的“最简单的”是limit=(end-start+step-(step>>31 | 1))/step
@Holger,谢谢。我的缺点是,我没有彻底测试极限。复制了你的公式now@Holger实际上,当涉及到intRange(Integer.MAX\u值、Integer.MIN\u值、Integer.MIN\u值)
等输入时,问题更加棘手。我编辑了答案,添加了我在解决方案上的最大努力,该解决方案考虑了所有的角落案例。不是很漂亮,但到目前为止我所有的测试都通过了。我不想使用long
类型,因为类似的long-range
方法也应该以相同的方式实现。舍入误差太大,例如intRange(0,9,2).forEach(System.out::println)代码>不会打印8
。除此之外,此解决方案也是唯一一个具有可预测大小的解决方案,它在内部甚至在顺序操作中使用,例如toArray()
。要想出一个对两个方向都有效的限制
计算并不容易。到目前为止,我得到的“最简单的”是limit=(end-start+step-(step>>31 | 1))/step
@Holger,谢谢。我的缺点是,我没有彻底测试极限。复制了你的公式now@Holger实际上,当涉及到intRange(Integer.MAX\u值、Integer.MIN\u值、Integer.MIN\u值)
等输入时,问题更加棘手。我编辑了答案,添加了我在解决方案上的最大努力,该解决方案考虑了所有的角落案例。不是很漂亮,但到目前为止我所有的测试都通过了。我不想使用long
类型,因为类似的longRange
方法也应该以相同的方式实现。
public static IntStream intRange(int startInclusive, int endExclusive, int step) {
if(step == 0)
throw new IllegalArgumentException("step = 0");
if(step == 1)
return IntStream.range(startInclusive, endExclusive);
if(step == -1) {
// Handled specially as number of elements can exceed Integer.MAX_VALUE
int sum = endExclusive+startInclusive;
return IntStream.range(endExclusive, startInclusive).map(x -> sum - x);
}
if((endExclusive > startInclusive ^ step > 0) || endExclusive == startInclusive)
return IntStream.empty();
int limit = (endExclusive-startInclusive)*Integer.signum(step)-1;
limit = Integer.divideUnsigned(limit, Math.abs(step));
return IntStream.rangeClosed(0, limit).map(x -> x * step + startInclusive);
}