【发布时间】:2016-11-05 04:07:16
【问题描述】:
我的问题基本上归结为将List 减少为一个链表,但从 reduce 函数推断的类型似乎不正确。
我的列表将如下所示
[0, 1, 2]
我希望 reduce 函数在每个 reduce 步骤中都这样做
null // identity (a Node)
Node(0, null) // Node a = null, int b = 0
Node(1, Node(0, null)) // Node a = Node(0, null), int b = 1
Node(2, Node(1, Node(0, null))) // Node a = Node(1, Node(0, null)), int b = 2
但是,reduce 函数似乎认为这不起作用,因为我猜它不认为身份是节点。
这是我的代码。
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Example {
static class Node {
int value;
Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
}
static Node reverse(List<Integer> list) {
return list.stream()
.reduce(null, (a, b) -> new Node(b, a)); // error: thinks a is an integer
}
void run() {
List<Integer> list = IntStream.range(0, 3)
.boxed()
.collect(Collectors.toList());
Node reversed = reverse(list);
}
public static void main(String[] args) {
new Example().run();
}
}
我做错了什么?
编辑 接受答案后,我的代码如下所示:
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Example {
static class Node {
int value;
Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
@Override
public String toString() {
return "Node{" +
"value=" + value +
", next=" + next +
'}';
}
}
static Node reverse(List<Integer> list) {
return list.stream()
.reduce(null, (n, i) -> {
System.out.println("Will happen"); // to demonstrate that this is called
return new Node(i, n);
}, (n1, n2) -> {
System.out.println("Won't happen"); // and this never is
return new Node(n1.value, n2);
});
}
void run() {
List<Integer> list = IntStream.range(0, 3)
.boxed()
.collect(Collectors.toList());
Node reversed = reverse(list);
System.out.println(reversed);
}
public static void main(String[] args) {
new Example().run();
}
}
现在打印出来了
Will happen
Will happen
Will happen
Node{value=2, next=Node{value=1, next=Node{value=0, next=null}}}
我仍然不知道为什么 Java 不能告诉 reduce 函数的第三个参数是不必要的,它永远不会被调用,但这是另一天的问题。
二次编辑
可以为这样的 reduce 操作创建一个新方法,因为 reduce 的第三个参数可以是一个什么都不做的函数。
static <T, U> U reduce(Stream<T> stream, U identity, BiFunction<U, ? super T, U> accumulator) {
return stream.reduce(identity, accumulator, (a, b) -> null);
}
static Node reverse(List<Integer> list) {
return reduce(list.stream(), null, (n, i) -> new Node(i, n));
}
【问题讨论】:
-
为什么不用
collect而不是reduce?collect更适合从 Stream 创建 Collection。 -
@Eran 我不喜欢它需要我实现 3 个方法
-
@michaelsnowden 尝试并行运行
Stream然后你需要合并器。 -
您真正在寻找 fold 操作而不是 reduce 操作,遗憾的是目前 Java 不支持该操作。见this answer。您可以使用
forEachOrdered模拟 fold 操作。
标签: java linked-list java-8 reduce