You can generate a Linked List using Stream API and specifically reduce() operation.
But keep in mind that in essence it's a tricky way to mimic the for loop (which will be a more suitable option) and this stream can't be executed in parallel.
In order to create a stream containing the required number of elements, there's no need for generating an array and then use it as a stream-source. Instead, we can create a stream by using either IntStream.range(), which expects start and end int values (it will work only if start < end) or IntStream.iterate().
Note that box() operation in required in order to transform the IntStream into a stream of objects in order to get access to this flavor of reduce(identity, accumulator, combiner), wich allows to provide the identity of the type that differs from the type of the elements in the stream.
This form of reduce() is not available with IntStream.
The tail node should be provided as the identity of reduce() operation. The accumulator function is responsible for generating the linked list in reversed order (from tail to head). The node returned as a result of the execution of the stream pipeline would be the head node.
Combiner function, which is used to combine partial results produces in parallel, throws an AssertionError because if we would allow parallel execution each thread will instantiate its own identity (the tail node), which means that nodes would be linked incorrectly.
int tailValue = 5;
int headValue = 1;
// generating the linked list
Node head = IntStream.range(headValue, tailValue)
.boxed()
.reduce(new Node(tailValue, null),
(Node node, Integer value) -> new Node(node.getValue() - 1, node),
(Node left, Node right) -> {throw new AssertionError("should not be used in parallel");});
// printing the linked list
Node cur = head;
while (cur != null) {
System.out.println(cur);
cur = cur.getNext();
}
Output:
Node { value = 1 }
Node { value = 2 }
Node { value = 3 }
Node { value = 4 }
Node { value = 5 }
A link to the Online Demo
Tried something like this, which does not compile
Node node = Arrays.stream(new int[]{1,2,3,4,5})
.map((i, n) -> new Node(i, n))
.reduce(null, new SingleList.Node(i, n)));
Arrays.stream(new int[]{1,2,3,4,5}) will produce an IntStream (not a Stream).
Operation map(), applied on the IntStream, expects an argument of type IntUnaryOperator, which is a function that takes a single argument of type int and returns int as well.
In order to transform the stream of primitives into a stream of objects, you should use mapToObj(), which expects an IntFunction (a function that takes a single int argument and returns an object).
The form of reduce(int identity, IntBinaryOperator combiner), which is available with IntStream expects the identity of primitive type int, and its combiner is of type IntBinaryOperator, i.e. it takes int and produces int. Therefore, it would not compile.
There is also a logical flaw in your solution - you are attempting to create a node for each steam element twice: first time inside the map() and than during the reduce() operation, which is clearly redundant.
According to the documentation map() is a stateless operation it should not be "aware" of the previously encountered elements. Which means it can't be helpful in generating nodes, because it's unable to provide the reference to the next node.
A dummy Node class used above:
public static class Node {
private int value;
private Node next;
public Node(int value, Node next) {
this.value = value;
this.next = next;
}
public int getValue() {
return value;
}
public Node getNext() {
return next;
}
@Override
public String toString() {
return "Node {" +
" value = " + value + " }";
}
}