【问题标题】:Fibonacci using Stream And BinaryOperator in Java在 Java 中使用 Stream 和 BinaryOperator 的斐波那契
【发布时间】:2019-04-15 16:13:59
【问题描述】:

我是学生,正在学习函数式 Java 8。我有项目要做,但我不明白这个函数接口是如何工作的。我的老师告诉我“你应该知道这一点”,我正在寻求帮助来理解这个问题。它应该计算斐波那契数列

我得到了这个代码

StreamUtils.generateRest(Stream.of(1, 1), (a, b) -> a + b)
    .limit(7)
    .forEach(System.out::println);

StreamUtils.generateRest(Stream.of("AAA", "BB", "KKKK"), (a, b) -> a + b)
    .limit(7)
    .forEach(System.out::println);

StreamUtils.generateRest(Stream.of(i -> 0), 
    (BinaryOperator<UnaryOperator<Integer>>) (f, g) -> (x -> x == 0 ? 1 : x * g.apply(x - 1)))
    .limit(10)
    .map(f -> f.apply(7))
    .forEach(System.out::println);

我做了类似的事情,但它不起作用

public class StreamUtils<T> {

    public static <T> Stream generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
        return Stream.of(stream.reduce((a, b) -> binaryOperator.apply(a, b)));
    }

}

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 但它不起作用..您在看这三种实现中的哪一种?当然,你应该知道他们都不是在做同样的事情。
  • 我认为 StreamUtils.generateRest() 的第一次和第二次运行做同样的事情
  • 第三个generateRest 调用应该打印什么? Stream 只有一个元素,BinaryOperator 忽略第一个参数。
  • 这里是使用 Java 8 流的斐波那契解决方案:stackoverflow.com/questions/30595844/…
  • 你能给出其中任何一个的预期输出吗? generateRest 的返回类型应该是Stream&lt;T&gt; 吗?原始类型只会使事情复杂化。

标签: java lambda java-8 java-stream functional-interface


【解决方案1】:

要使第一个示例工作,您需要实现以下内容:

private static class StreamUtils<T> {
    public static <T> Stream generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
        return Stream.iterate(stream.toArray(), p -> new Object[]{p[1], binaryOperator.apply((T) p[0], (T) p[1])})
            .flatMap(p -> Stream.of(p[0]));
    }
}

它从您的输入流创建数组,然后将传递的函数应用于两个元素,将上一次迭代的结果移动到位置0,因为我们需要前两个值来计算下一个。 然后它会创建无限的计算斐波那契元素流。

输出是:

1
1
2
3
5
8
13

以及具有正确泛型用法的版本,因为您的初始结构会生成原始类型。

private static class StreamUtils {
    public static <T> Stream<T> generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
        return Stream.iterate(stream.toArray(), p -> new Object[]{p[1], binaryOperator.apply((T) p[0], (T) p[1])})
            .flatMap(p -> Stream.of((T) p[0]));
    }
}

【讨论】:

  • @anik 不知道示例 #2 的输出应该是什么,如果您解释我可以尝试提供帮助,示例 #3 无法编译
【解决方案2】:

我假设拥有超过 2 个项目意味着 A、B、C、A+B、B+C、C+(A+B)、(A+B)+(B+C) 等, 1 项表示 A、A+A、A+(A+A)、(A+A)+(A+(A+A)) 等,其中 + 是二元运算符。

基本上,您将流转换为数组,然后使用Stream.generate 并在每一步生成元素之后的元素,将数组左移以适应新元素,并返回旧的第一个元素(不再在数组中)。请注意,由于这有副作用(修改外部数组),它不能与 .parallel() 一起使用。

@SuppressWarnings("unchecked")
public static <T> Stream<T> generateRest(Stream<T> stream, BinaryOperator<T> binaryOperator) {
    T[] t = (T[]) stream.toArray();
    if (t.length == 1) {
        t = (T[]) new Object[] { t[0], binaryOperator.apply(t[0], t[0]) };
    }
    final T[] items = t;
    return Stream.generate(() -> {
        T first = items[0];
        T next = binaryOperator.apply(items[0], items[1]);
        System.arraycopy(items, 1, items, 0, items.length - 1);
        items[items.length - 1] = next;
        return first;
    });
}

输出:

1
1
2
3
5
8
13
AAA
BB
KKKK
AAABB
BBKKKK
KKKKAAABB
AAABBBBKKKK
0
0
0
0
0
0
0
0
5040
5040

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多