如何在Java中从右侧减少有限的流(例如ArrayList)?

如何在Java中从右侧减少有限的流(例如ArrayList)?,java,functional-programming,java-stream,Java,Functional Programming,Java Stream,我想使用reduce将列表转换为自实现的链表。我设法以相反的顺序做到了: 导入java.util.array; 导入java.util.List; 公共类反向{ 静态类节点{ int-val; 节点下一步; 节点(int v,节点n){ val=v; next=n; } } 公共静态void main(字符串[]args){ 列表编号=数组.asList(1,2,3,4,5,6); 节点结果=编号 .stream() .reduce(空, (节点,val)->新节点(val,节点), (n1,n

我想使用
reduce
将列表转换为自实现的链表。我设法以相反的顺序做到了:

导入java.util.array;
导入java.util.List;
公共类反向{
静态类节点{
int-val;
节点下一步;
节点(int v,节点n){
val=v;
next=n;
}
}
公共静态void main(字符串[]args){
列表编号=数组.asList(1,2,3,4,5,6);
节点结果=编号
.stream()
.reduce(空,
(节点,val)->新节点(val,节点),
(n1,n2)->新节点(-1,null));
while(结果!=null){
System.out.println(result.val);
result=result.next;
}
}
}
输出为

6
5
4
3
2
1

我认为为了获得正确的结果,我可能需要在其他语言中使用foldRight或reduceRight之类的东西。java是否提供了类似的功能,因为流被保证是有限的?

从最新的java 16开始,当前的流API不提供任何“右起”的操作,例如“reduceRight”

唯一可能的解决方法是在应用缩减之前,使用方法颠倒集合中项目的顺序

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
Collections.reverse(numbers);
Node result = numbers
    .stream()
    .reduce(null,
            (node, val) -> new Node(val, node),
            (n1, n2) -> new Node(-1, null));

List number=Arrays.asList(1,2,3,4,5,6);
收藏。反面(数字);
节点结果=编号
.stream()
.reduce(空,
(节点,val)->新节点(val,节点),
(n1,n2)->新节点(-1,null));

请在此处阅读更多信息:

您可以提供标识并将其用作起点:

public class Test {

    public static void main(String[] args) throws Exception {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        Node result = new Node();

        numbers.stream()
           .reduce(result,
                  (node, val) -> {node.next= new Node(val, null); return node.next;},
                  (n1, n2) -> new Node(-1, null));

        result = result.next;
        while(result != null) {
            System.out.println(result.val);
            result = result.next;
        }
    }
}
class Node {
    int val;
    Node next;

    Node(){}
    Node(int v, Node n) {
        val = v;
        next = n;
    }
}

正如它们的名字所暗示的,流是单向的。它们就像生产线。你不能只是说“先把生产线上的最后一件东西给我!”!“因为传送带不是这样工作的。你可以在生产线上的某个点等待收集所有物品,收集物品时,按相反的顺序订购。然后再将它们放在生产线上。”

numbers.stream().collect(Collectors.toCollection(ArrayDeque::new)).stream()
    .reduce(...)
在这里,我将它收集到一个
ArrayDeque
中,由于
ArrayDeque
是一个堆栈结构,它会将其反转。然后您可以使用
reduce
来查看它

请注意,“反转列表”部分根本不需要流:

new ArrayDeque<>(number).stream().reduce(...)
// or the many other ways of reversing a list
然后你可以做:

Node result = numbers
    .stream()
    .collect(CollectHelper::new, CollectHelper::accumulate, CollectHelper::combine).head;

可能是相关的,如果不是黑客但整洁的技术。让我想起了过去使用C指针的美好时光。
static class CollectHelper {
  private Node tail;
  private Node head;

  public void accumulate(int i) {
    if (head == null) {
      head = new Node(i, null);
      tail = head;
    } else {
      tail.next = new Node(i, null);
      tail = tail.next;
    }
  }

  public void combine(CollectHelper other) {
    if (other.head == null) return;
    tail.next = other.head;
    tail = other.tail;
  }
}
Node result = numbers
    .stream()
    .collect(CollectHelper::new, CollectHelper::accumulate, CollectHelper::combine).head;