4

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.

8
  • What is the element type of the input stream? Commented Jun 22, 2018 at 16:44
  • 1
    There's no FloatStream, so I don't think this is possible without writing a custom collector which converts from either Float or double. Commented Jun 22, 2018 at 16:46
  • 1
    Would a double[] do? If so, you could use Stream#mapToDouble(...) to obtain a DoubleStream Commented Jun 22, 2018 at 16:46
  • Why float and not double? Then you could use DoubleStream. Commented Jun 22, 2018 at 16:46
  • 3
    The duplicate is exactly not what OP wants. If anything, this is what OP wants. But even this does not answer the question as to why it does not work. Voting to reopen. Commented Jun 22, 2018 at 16:55

4 Answers 4

4

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:

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.

Here is the use:

Float[] data = input.map(Float::valueOf).toArray(Float[]::new);
Sign up to request clarification or add additional context in comments.

Comments

3

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[].

1 Comment

The missing size is actually a typo, in the code I have got it. I'll not fix the question or your answer will lose meaning. Thank you
3

There is a better way with my library abacus-common:

float[] result = Stream.of(input).mapToFloat(Float::parseFloat).toArray();

1 Comment

Thank you for doing what the core Java library team couldn't be arsed to do. Single Precision is handy anywhere hardware acceleration is involved.
0

You can use the value from the Float Object through the floatValue() method to create a array:

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

for(int x = 0; x < data.length; x ++) {
    primData[x] = data[x].floatValue();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.