Java Streams toArray with primitives

时间:2017-11-02 14:55:01

标签: java arrays generics lambda

在办公室周围向人们讲述这一点让我意识到,如果没有我如何到达这里的背景,他们的反应始终是"你做错了#34;所以这里有#s背景:

我必须处理由另一个团队使用ICE(https://doc.zeroc.com/display/Ice37/Ice+Overview)创建的糟糕对象,并且想为锅炉板代码编写一个实用程序,我一直在写作。

我需要处理的一个对象是浮动和字符串的容器。我只想要浮点值。

public class FloatWrapper {
    public String   StringValue;
    public float    FloatValue;

    public FloatWrapper(float f) {
        this.FloatValue = f;
    }

    public FloatWrapper(String s) {
        this.StringValue = s;
    }

    public FloatWrapper(float f, String s) {
        this.FloatValue = f;
        this.StringValue = s;
    }
}

这个容器以2D数组的形式交付给我,所以我想要一个float [] []。让我们从1维开始

FloatWrapper[] wrappers = new FloatWrapper[] { 
    new FloatWrapper(1.0f), 
    new FloatWrapper(2.0f) 
};

Float[] asFloats = Arrays.stream(wrappers)
    .map(f -> f.FloatValue)
    .toArray(Float[]::new);

这很容易。让我们试一下2D数组。

// Make a lovely method for what I have above
public Float[] convert1Darray(FloatWrapper[] wrappers) {
    return Arrays.stream(wrappers)
            .map(f -> f.FloatValue)
            .toArray(Float[]::new);
}

public static Float[][] convert2Darray(FloatWrapper[][] wrappers) {
    return Arrays.stream(wrappers)
            .map(f -> convert1Darray(f))
            .toArray(Float[][]::new);
}

...

// Create a 2D array
FloatWrapper[][] wrappers2d = new FloatWrapper[][] { 
    { new FloatWrapper(1.0f), new FloatWrapper(2.0f) }, 
    { new FloatWrapper(3.0f), new FloatWrapper(4.0f) }
};

Float[][] floats2d = convert2Darray(wrappers2d);

轰!

拥有原始花车真是太好了(只是,好吧!)你们中间干瘪的人可以看到我去的地方......

事实证明,你不能很容易地在' toArray'中使用原始花车。呼叫。 Apache commons将对此进行排序

public static float[] convert1DprimitiveArray(FloatWrapper[] wrappers) {
    return ArrayUtils.toPrimitive(
            Arrays.stream(wrappers)
                    .map(f -> f.FloatValue)
                    .toArray(Float[]::new));
}

public static float[][] convert2DprimitiveArray(FloatWrapper[][] wrappers) {
    return Arrays.stream(wrappers)
            .map(f -> convert1DprimitiveArray(f))
            .toArray(float[][]::new);
}

....等一下。为什么我可以使用' toArray(float [] [] :: new)'但不是#Array(float [] :: new)' ?

现在浮动办公室的争论是“浮动[] ::新'电话是非法的,因为你不能打电话给新的'在一个原始的。

但那不是它正在做的事情。这只是IntFunction的简写

让我们分解

此:

Arrays.stream(wrappers1d).map(f -> f.FloatValue).toArray(Float[]::new);

相当于:

Arrays.stream(wrappers1d).map(f -> f.FloatValue).toArray(new IntFunction<Float[]>() {
    @Override
    public Float[] apply(int size) {
        return new Float[size];
    }
});

那么,你是不是可以创建IntFuntion类型的东西?

不。完全允许:

IntFunction<float[]> happyToCompile = new IntFunction<float[]>() {
    @Override
    public float[] apply(int size) {
        return new float[size];
    }
};

执行该功能会使您等同于

new float[]{ 0.0f, 0.0f };

所以,我半教育的猜测是,当你有一个2d数组而不是1d数组时,IntFunction会发生一些类型推断。但是,&#39;可以&#39;它有用吗?

3 个答案:

答案 0 :(得分:2)

  

为什么我可以使用'toArray(float [] [] :: new)'而不是   'toArray(float [] :: new)'?

正如您所说,Arrays.stream(wrappers).map(f -> f.FloatValue)Stream<Float>,因此toArray(float[]::new)不起作用,因为您需要提供IntFunction<Float[]>,而不是IntFunction<float[]>。< / p>

另一方面,Arrays.stream(wrappers).map(f -> convert1DprimitiveArray(f))Stream<float[]>,因此toArray(IntFunction<A[]>)需要IntFunction<float[][]>,这是float[][]::new的用途。

如果你有一个.toArray(float[]::new),那么

Stream<float>会有效,这是不可能的,因为你不能将原始类型作为通用参数。

答案 1 :(得分:1)

发生该错误,因为float没有包装流。因此,您无法使用FloatStream或类似内容。

因此,当你分析Stream.toArray()实际上是什么时,你会得到这样的东西:

  

返回一个数组T[],它在此流中保存T类型的每个对象

问题来自于T,因为您有一个包含floats的流,存储在WrapperClass Float中(因为基元不能与泛型一起使用)。

现在,当您尝试将Float转换为float时,java会使用auto-unboxing为您执行此操作。不好的是,它对于数组来说并不相同。

  

在java中,一个基元数组可以直接转换为它的特定包装类型。

所以Float[] floats = new float[10];给出了编译错误。

现在你问自己:为什么float[][]会起作用?。好吧,如果您查看它,那么您会看到float[]Objectfloat流 - 数组是有效的,因为它们可以作为对象引用。这就是为什么float[][]::new有效的原因。它与之前的描述相匹配:返回一个数组T [],它包含此流中类型为T的每个对象,因为float[]实际上是T类型和{{ 1}}也是有效的。

答案 2 :(得分:0)

  

为什么我可以使用'toArray(float [] [] :: new)'而不是'toArray(float [] :: new)

因为在map调用之后你有一个数组流,并且要创建一个数组流,你需要创建一个数组数组,而不是float s。

要获取基元类型,您必须首先转换为DoubleStream

Arrays.stream(wrappers).mapToDouble(FloatWrapper::getFloat)

它为您提供原始流;那些你应该能够通过一些额外的魔法制作浮点阵列。