如何从Stream获取ObservableFloatArray? [英] How to get an ObservableFloatArray from a Stream?

查看:140
本文介绍了如何从Stream获取ObservableFloatArray?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这与一个几乎相同,但方向相反。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆