我试图使用前面的两个值,使用java 8的流来计算一个值的乘法。我想要调用一个函数,它将返回一个数组/列表/集合。我正在创建一个列表,并在其中添加1,2。
假设列表名是结果。
public static void main (String[] args) {
List<Integer> result = new ArrayList<Integer>();
result.add(1);
result.add(2);
int n = 5; //n can be anything, choosing 5 for this example
res(n, result);
//print result which should be [1, 2, 2, 4, 8]
}
public static List<Integer> res(int n, List<Integer> result ) {
result.stream()
.limit(n)
.reduce(identity, (base,index) -> base);
//return result;
}
现在,问题是试图将结果传递到流中,以便使用流更新列表中的新值。根据java教程,这是可能的,尽管效率很低。
“如果减少操作涉及向集合添加元素,那么每次累加器函数处理元素时,它都会创建一个包含元素的新集合,这是效率低下的。”
我是否需要使用可选的第三个参数BinaryOperator组合器来组合列表+结果?
<U> U reduce(U identity,
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
简而言之,我想传递一个包含两个值的列表,并让函数查找前两个值的乘法(1,2),将其添加到列表中,并找到最后两个值(2,2)的乘法,并将其添加到列表中,直到流达到极限为止。
发布于 2014-09-16 17:40:08
看起来你在尝试实现一个重复的关系。reduce
方法将一些函数应用于流中的一组预先存在的值。您不能使用reduce
并将还原器函数的中间结果“反馈”到流中,这是实现递归关系所需的。
使用流实现递归关系的方法是使用流工厂方法之一Stream.generate
或Stream.iterate
。iterate
工厂似乎提出了最明显的方法。在您的示例中,需要为每个递归函数的应用程序保留的状态需要两个int,因此不幸的是,我们必须创建一个对象来保存这些对象:
static class IntPair {
final int a, b;
IntPair(int a_, int b_) {
a = a_; b = b_;
}
}
使用此状态对象,您可以创建一个实现所需重复使用的流:
Stream.iterate(new IntPair(1, 2), p -> new IntPair(p.b, p.a * p.b))
一旦有了这样的流,将值收集到列表中是一件很简单的事情:
List<Integer> output =
Stream.iterate(new IntPair(1, 2), p -> new IntPair(p.b, p.a * p.b))
.limit(5)
.map(pair -> pair.a)
.collect(Collectors.toList());
System.out.println(output);
[1, 2, 2, 4, 8]
另外,您可以使用相同的技术来生成Fibonacci序列。您所做的就是提供一个不同的起始值和迭代函数:
Stream.iterate(new IntPair(0, 1), p -> new IntPair(p.b, p.a + p.b))
您还可以使用Stream.generate
实现类似的递归关系。这还需要一个助手类。helper类实现结果值的Supplier
,但它也需要维护状态。因此,它需要是可变的,这在我的书中是有点恶心的。迭代函数还需要放入生成器对象中。这使得它不像IntPair
对象那么灵活,后者可以用于创建任意递归。
发布于 2014-09-17 04:45:51
为了完整起见,这里有一个不需要额外类的解决方案。
List<Integer> output = Stream.iterate(
(ToIntFunction<IntBinaryOperator>)f -> f.applyAsInt(1, 2),
prev -> f -> prev.applyAsInt((a, b) -> f.applyAsInt(b, a*b) )
)
.limit(9).map(pair -> pair.applyAsInt((a, b)->a))
.collect(Collectors.toList());
这是一种不需要中间值存储的功能方法。但是,由于Java不是一种函数式编程语言,也没有对这样的递归函数定义进行优化,因此不建议对较大的流进行优化。
因为在这个例子中,一个更大的流无论如何都会在数值上溢出,而且计算成本很低,所以这种方法是可行的。但是对于其他用例,在用普通的Java (如Stuart Marks’ answer)解决这样的问题时,您肯定会更喜欢存储对象。
https://stackoverflow.com/questions/25880331
复制相似问题