This is nearly the same question as this one, but in the opposite direction.
I know there's no FloatStream
in Java 8, and there're no many use cases for float[], but I have one:
Dealing with TriangleMesh
in JavaFX 3D, you have to provide an ObservableFloatArray
for the 3D coordinates of the vertices of the whole mesh.
As a result of some calculations I'll have all these coordinates in a List
, and to add all of them at once to the mesh, I'll call triangleMesh.getPoints().addAll()
, using one of the following methods:
where ObservableFloatArray
can be created using FXCollections.observableFloatArray()
, FXCollections.observableFloatArray(ObservableFloatArray array)
or FXCollections.observableFloatArray(float... values)
.
Let's say I have this pojo for each vertex:
private class Vertex {
private final float x;
private final float y;
private final float z;
public Vertex(float x, float y, float z){
this.x=x; this.y=y; this.z=z;
}
public float[] getCoordenates(){
return new float[]{x,y,z};
}
}
and after performing some calculations I have List<Vertex> listVertices
. I'll need to generate float[] arrayVertices
to finally call triangleMesh.getPoints().addAll(arrayVertices);
.
For now this is what I'm doing:
listVertices.forEach(vertex->triangleMesh.getPoints().addAll(vertex.getCoordenates()));
But this triggers the associated listener on every new vertex added to the observable array, and for high number of vertices this affects performance.
Should FloatStream
and flatMapToFloat()
exist, I'd do something like this:
float[] arrayVertices = listVertices.stream()
.map(vertex->FloatStream.of(vertex.getCoordenates()))
.flatMapToFloat(f->f).toArray();
triangleMesh.getPoints().addAll(arrayVertices);
like I actually do with a list of int[] for face indices:
int[] arrayFaces = listFaces.stream()
.map(face->IntStream.of(face.getFaceIndices()))
.flatMapToInt(i->i).toArray();
triangleMesh.getFaces().addAll(arrayFaces);
But as far as I know, there's no way using streams.
Thanks in advance for any possible solution involving streams.
Keep in mind that a Stream
defines an operation rather that a storage. So for most operations, using a float
provides only little benefit over double
values when CPU registers are used. There might be a theoretical improvement for operations that could be accelerated using SSE or GPU, but that’s not relevant here.
So you can use a DoubleStream
for that operation, the only thing you need is a collector capable of collecting a DoubleStream
into a float[]
array:
float[] arrayVertices = listVertices.stream()
.flatMapToDouble(vertex->DoubleStream.of(vertex.x, vertex.y, vertex.z))
.collect(FaCollector::new, FaCollector::add, FaCollector::join)
.toArray();
static class FaCollector {
float[] curr=new float[64];
int size;
void add(double d) {
if(curr.length==size) curr=Arrays.copyOf(curr, size*2);
curr[size++]=(float)d;
}
void join(FaCollector other) {
if(size+other.size > curr.length)
curr=Arrays.copyOf(curr, size+other.size);
System.arraycopy(other.curr, 0, curr, size, other.size);
size+=other.size;
}
float[] toArray() {
if(size!=curr.length) curr=Arrays.copyOf(curr, size);
return curr;
}
}
This supports parallel processing, however, for an operation that merely consist of data copying only, there is no benefit from parallel processing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With