How to Create a Stream from an Array

How can I create a stream from an array?

You can use Arrays.stream E.g.

Arrays.stream(array);

You can also use Stream.of as mentioned by @fge , which looks like

public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}

But note Stream.of(intArray) will return Stream<int[]> whereas Arrays.stream(intArr) will return IntStream providing you pass an array of type int[]. So in a nutshell for primitives type you can observe the difference between 2 methods E.g.

int[] arr = {1, 2};
Stream<int[]> arr1 = Stream.of(arr);

IntStream stream2 = Arrays.stream(arr);

When you pass primitive array to Arrays.stream, the following code is invoked

public static IntStream stream(int[] array) {
return stream(array, 0, array.length);
}

and when you pass primitive array to Stream.of the following code is invoked

 public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

Hence you get different results.

Updated: As mentioned by Stuart Marks comment
The subrange overload of Arrays.stream is preferable to using Stream.of(array).skip(n).limit(m) because the former results in a SIZED stream whereas the latter does not. The reason is that limit(m) doesn't know whether the size is m or less than m, whereas Arrays.stream does range checks and knows the exact size of the stream
You can read the source code for stream implementation returned by Arrays.stream(array,start,end) here, whereas for stream implementation returned by Stream.of(array).skip().limit() is within this method.

How to convert a Java 8 Stream to an Array?

The easiest method is to use the toArray(IntFunction<A[]> generator) method with an array constructor reference. This is suggested in the API documentation for the method.

String[] stringArray = stringStream.toArray(String[]::new);

What it does is find a method that takes in an integer (the size) as argument, and returns a String[], which is exactly what (one of the overloads of) new String[] does.

You could also write your own IntFunction:

Stream<String> stringStream = ...;
String[] stringArray = stringStream.toArray(size -> new String[size]);

The purpose of the IntFunction<A[]> generator is to convert an integer, the size of the array, to a new array.

Example code:

Stream<String> stringStream = Stream.of("a", "b", "c");
String[] stringArray = stringStream.toArray(size -> new String[size]);
Arrays.stream(stringArray).forEach(System.out::println);

Prints:

a
b
c

Java 8 Stream and operation on arrays

There are new methods added to java.util.Arrays to convert an array into a Java 8 stream which can then be used for summing etc.

int sum =  Arrays.stream(myIntArray).sum();

Multiplying two arrays is a little more difficult because I can't think of a way to get the value AND the index at the same time as a Stream operation. This means you probably have to stream over the indexes of the array.

//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...

int[] result = new int[a.length];

IntStream.range(0, a.length).forEach(i -> result[i] = a[i] * b[i]);

Commenter @Holger points out you can use the map method instead of forEach like this:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();

How can I create a StreamString[] with only one element with Stream.of?

Solution

Stream<String[]> stream = Stream.<String[]>of(tropicalFruits);

or

Stream<String[]> stream = Stream.of(new String[][]{tropicalFruits});

Explanation

To produce a Stream<T>, Stream.of takes either T or T....

A T[] parameter perfectly applies to the second signature.

Therefore, passing a String[] invokes the Stream.of(String...) version.

To change this behaviour, we need to provide some extra information about T (1) or define it more clearly (=unambiguously) (2).

There are two ideas came to my mind:

  1. To specify a type argument of the method explicitly to use the first signature.

    Stream.<String[]>of(new String[]{}) will produce a Stream<String[]>.
  2. To wrap a T[] value in a T[][] array to use the second signature.

    Stream.of(new String[][]{}) will produce a Stream<String[]>.

How to create a map out of two arrays using streams in Java?

use IntStream and collect to a map:

IntStream.range(0, a.length)
.boxed()
.collect(toMap(i -> a[i], i -> b[i]));

Convert an array into map using stream

Your current stream pipeline converts the original values to new values, so you can't collect it into a Map that contains both the original values and the new values.

You can achieve it if instead of map you use .collect(Collectors.toMap()) and perform the multiplication in toMap():

Map<Integer,Integer> map =
myList.stream()
.collect(Collectors.toMap(Function.identity(),
n -> n * 5));

In you still want to use map, you can retain the original values by converting each of them to a Map.Entry:

Map<Integer,Integer> map =
myList.stream()
.map (n -> new SimpleEntry<> (n, n * 5))
.collect(Collectors.toMap(Map.Entry::getKey,
Map.Entry::getValue));

Instantiating array of objects with streams

Eran's answer has the general idea of what to do, but is missing a few key details.

Using Stream.of on an int[] will result in a Stream<int[]>; one of the magical artifacts of Java.

Instead, you should use Arrays.stream or IntStream.of to get a IntStream (remember, primitives can't be a parameter).

For the map operation, you can use a method reference to Layer::new.

This all boils down to this new snippit

List<Layer> layers = IntStream.of(layer_sizes).boxed().map(Layer::new).collect(Collectors.toList());

Java: do streams allocate significant space while streaming over an array?

The answer is:

[A] an implementation detail. The java spec simply isn't going to tell you, and therefore any exact answer needs to be caveated with '.. on this hardware, this OS, this VM impl, this version, under these circumstances'. However...

[B] Whatever the answer is, it is both 'pretty fast / not much space', and it is definitely 'not dependent on the value of N'.

The 'Stream' in stream is not chosen for fun: The stream API does, in fact, stream. It does not take the entire array, then make a new object containing all values ready for streaming, then limit makes yet another new giant array (one size smaller), and then mapToInt makes yet another. That is not how it works.

Stream is a pipeline. Nothing happens until you run a terminal command (sum is terminal). You can check this:

Arrays.stream(queries).mapToInt(i -> {
System.out.println(i);
return i.intValue();
});

This doesn't print anything. At all. Because this is just a stream process half-baked, no terminal, it doesn't 'flow'.

If you invoke sum on the above, THEN the prints start happening. Specifically, the terminal (sum(), here) start 'pulling values from the stream'. This travels up. sum asks mapToInt for a value, and to do this, mapToInt asks limit for a value (and will then take that value, roll it through the i -> i lambda, and provide that to sum). limit will then ask Arrays.stream for a value and that will then actually read a single item from the array. There ARE intermediate tracker objects involved, but their size doesn't depend on N. For example, the object returned by Arrays.stream(queries) holds a ref to the queries array (about 64 bits of data regardless of how large that array is; just a pointer), and an int value that knows where we're at 1.

The object representing the limit part of it all just has a single int that tracks how many values have been provided so far. limit acts like there are no more values to provide when the thing it is pulling from runs out or limit items have already been provided, whichever occurs sooner.

And so on. Thus, exactly how big those tracker objects are is an implementation detail, but, they are 'small' (at least, relative to a million-ints array!), and do not depend on the size of the stream. In fact, literally infinite streams can exist, no problem. And they do - check the API of Stream itself, where you can rather easily make a stream that returns an infinite amount of 1 values, for example.

[1] I'm oversimplifying. Streams also have the property that depending on a few circumstances, they can be parallellized. When you involve counters, parallelizing becomes very difficult, so these trackers are a bit more complicated. If you want the full details, look at Spliterator, and StreamUtils. But, this oversimplified explanation is sufficient for understanding that no amount of stream intermediate ops are going to put you at risk of running out of memory.



Related Topics



Leave a reply



Submit