这个问题几乎与此one相同,但是方向相反。

我知道Java 8中没有FloatStream,float []的用例不多,但是我有一个用例:

在JavaFX 3D中处理TriangleMesh时,您必须为整个网格的顶点的3D坐标提供ObservableFloatArray

作为一些计算的结果,我将所有这些坐标存储在List中,并将所有这些坐标一次性添加到网格中,我将使用以下方法之一调用triangleMesh.getPoints().addAll():

  • addAll(ObservableFloatArray src)
  • addAll(float ... elements)
  • addAll(ObservableFloatArray src,int srcIndex,int length)
  • addAll(float [] src,int srcIndex,int length)

  • 可以使用ObservableFloatArrayFXCollections.observableFloatArray()FXCollections.observableFloatArray(ObservableFloatArray array)创建FXCollections.observableFloatArray(float... values)

    假设每个顶点都有这个pojo:
    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};
        }
    }
    

    执行一些计算后,我有了List<Vertex> listVertices。我需要生成float[] arrayVertices才能最终调用triangleMesh.getPoints().addAll(arrayVertices);

    现在,这就是我正在做的事情:
    listVertices.forEach(vertex->triangleMesh.getPoints().addAll(vertex.getCoordenates()));
    

    但这会在添加到可观察数组的每个新顶点上触发关联的监听器,并且对于大量的顶点,这会影响性能。

    如果存在FloatStreamflatMapToFloat(),我将执行以下操作:
    float[] arrayVertices = listVertices.stream()
                .map(vertex->FloatStream.of(vertex.getCoordenates()))
                .flatMapToFloat(f->f).toArray();
    triangleMesh.getPoints().addAll(arrayVertices);
    

    就像我实际上使用int []的人脸索引列表一样:
    int[] arrayFaces = listFaces.stream()
                .map(face->IntStream.of(face.getFaceIndices()))
                .flatMapToInt(i->i).toArray();
    triangleMesh.getFaces().addAll(arrayFaces);
    

    但据我所知,无法使用流。

    预先感谢任何涉及流的可能解决方案。

    最佳答案

    请记住,Stream定义了一个操作而不是一个存储。因此,对于大多数操作,当使用CPU寄存器时,使用float仅比double值提供的好处很小。从理论上讲,可以使用SSE或GPU加速操作的改进,但这与本文无关。

    因此,您可以使用DoubleStream进行该操作,唯一需要的是一个能够将DoubleStream收集到float[]数组中的收集器:

    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;
        }
    }
    

    这支持并行处理,但是,对于仅包含数据复制的操作,并行处理没有任何好处。

    10-05 18:41