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:
- To specify a type argument of the method explicitly to use the first signature.
Stream.<String[]>of(new String[]{})
will produce aStream<String[]>
. - To wrap a
T[]
value in aT[][]
array to use the second signature.Stream.of(new String[][]{})
will produce aStream<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
Calculating All of the Subsets of a Set of Numbers
Why Doesn't Java Allow Generic Subclasses of Throwable
Spring-Batch Without Persisting Metadata to Database
Connecting an Input Stream to an Outputstream
Java Enum and Additional Class Files
Why Is an Instance Variable of the Superclass Not Overridden by a Subclass
Updating UI from Different Threads in Javafx
Why Is Javafx Is Not Included in Openjdk 8 on Ubuntu Wily (15.10)
How to Unmap a File from Memory Mapped Using Filechannel in Java
Should I Use String.Isempty() or "".Equals(String)
Convert String to Calendar Object in Java
How to Test to See If a Double Is Equal to Nan
Reverse a Comparator in Java 8