如何从Stream获取ObservableFloatArray? [英] How to get an ObservableFloatArray from a Stream?
问题描述
这与一个几乎相同,但方向相反。
This is nearly the same question as this one, but in the opposite direction.
我知道Java 8中没有 FloatStream
,并且没有多少float []的用例,但我有一个:
I know there's no FloatStream
in Java 8, and there're no many use cases for float[], but I have one:
在JavaFX 3D中处理 TriangleMesh
,你必须为整个网格的顶点的3D坐标提供 ObservableFloatArray
。
Dealing with TriangleMesh
in JavaFX 3D, you have to provide an ObservableFloatArray
for the 3D coordinates of the vertices of the whole mesh.
作为一些计算的结果,我将在 List
中包含所有这些坐标,并添加所有它们一次到网格,我将使用以下方法之一调用 triangleMesh.getPoints()。addAll()
:
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:
- addAll(ObservableFloatArray src)
- addAll(float ... elements)
- addAll( ObservableFloatArray src,int srcIndex,int length)
- addAll(float [] src,int srcIndex,int length)
- addAll(ObservableFloatArray src)
- addAll(float... elements)
- addAll(ObservableFloatArray src, int srcIndex, int length)
- addAll(float[] src, int srcIndex, int length)
其中 ObservableFloatArray
可以使用 FXCollections.observableFloatArray()
,创建FXCollections.observableFloatArray(ObservableFloatArray数组)
或 FXCollections.observableFloatArray(float ... values)
。
假设我为每个顶点都有这个pojo:
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};
}
}
在执行一些计算后,我有列表与LT;顶点> listVertices
。我需要生成 float [] arrayVertices
以最终调用 triangleMesh.getPoints()。addAll(arrayVertices);
。
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.
应该 FloatStream
和 flatMapToFloat()
存在,我会做这样的事情:
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);
就像我实际使用面部索引的int []列表一样:
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.
推荐答案
请记住 Stream
定义一个操作而不是存储。因此,对于大多数操作,使用 float
在使用CPU寄存器时仅比 double
值提供的好处不大。对于可以使用SSE或GPU加速的操作可能存在理论上的改进,但这与此处无关。
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.
因此您可以使用 DoubleStream
对于该操作,您唯一需要的是能够将 DoubleStream
收集到 float []中的收集器
数组:
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.
这篇关于如何从Stream获取ObservableFloatArray?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!