Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Java stream of strings to array of float

I'm trying to find an elegant way to convert a Stream<String> to float[].

Until now I've come out with:

Float[] data = input.map(Float::valueOf).toArray(Float[]::new);

But I actually need a float[] and when I try:

float[] data = input.map(x -> Float.parseFloat(x)).toArray(size -> new float[]);

I get an error cannot convert Object[] to float[], which I don't really understand.

like image 208
Gianluca Avatar asked Sep 06 '25 08:09

Gianluca


2 Answers

There is no way of getting float[] directly from any Stream in Java yet. There are "only" 3 available converting mechanisms to numeric Stream interfaces:

  • mapToInt(ToIntFunction<? super T> mapper) -> IntStream
  • mapToLong(ToLongFunction<? super T> mapper) -> LongStream
  • mapToDouble(ToDoubleFunction<? super T> mapper) -> DoubleStream

Thus the only way is to use double instead, which is fairly easy:

double[] data = input.mapToDouble(Double::parseDouble).toArray();

If you insist to get the float[] from double[], it's another issue where might help the Guava library:

float[] floatArray = Floats.toArray(Doubles.asList(data));
// You can collect Stream to a Collection and pass directly Floats.toArray(list);

Or a simple for-loop:

float[] floatArray = new float[data.length];
for (int i = 0 ; i < data.length; i++) {
    floatArray[i] = (float) data[i];
}

Alternatively, you might use the method toArray(IntFunction<A[]> generator) which returns the array of an Object type. However, to unbox Float, you have to use the for-loop again in the very same way - it gives no difference except you can work with Float[] directly, although boxed.

  • map(Function<? super T,? extends R> mapper) -> Stream<R>

Here is the use:

Float[] data = input.map(Float::valueOf).toArray(Float[]::new);
like image 127
Nikolas Charalambidis Avatar answered Sep 10 '25 12:09

Nikolas Charalambidis


There is a minor error in your code, which we will fix first to reveal the larger problem at hand:

float[] data = input.map(x -> Float.parseFloat(x)).toArray(size -> new float[]);

should be:

float[] data = input.map(x -> Float.parseFloat(x)).toArray(size -> new float[size]);
                                                                             ^this is new

Even if it might not seem like it, your question is realted to generics. Let us take a look at the definition of Stream#toArray(...):

public <A> A[] toArray​(IntFunction<A[]> generator)

Since this method is generic in A, the type A must not be a primitive. You, on the other hand, try to set A to float (this is done through type inference, this is why you do not see the generic parameters in your code). The compiler now complains that:

error: incompatible types: inference variable A has incompatible bounds
    float[] data = input.stream().map(x -> Float.parseFloat(x)).toArray(size -> new float[size]);
                                                                       ^
    equality constraints: float
    upper bounds: Object
  where A is a type-variable:
    A extends Object declared in method <A>toArray(IntFunction<A[]>)
1 error

This question and its answer provide solutions/workarounds to the problem of converting a String-stream to a float[].

like image 39
Turing85 Avatar answered Sep 10 '25 11:09

Turing85