在办公室里与人谈论这件事让我意识到,如果不知道我是怎么做到的背景信息,他们的反应总是"你做错了",所以这就是背景:
我必须处理由另一个团队使用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 array)的形式交付给我的,因此我想要一个浮点数二维数组(float[][])。让我们从一维数组开始。
FloatWrapper[] wrappers = new FloatWrapper[] {
new FloatWrapper(1.0f),
new FloatWrapper(2.0f)
};
Float[] asFloats = Arrays.stream(wrappers)
.map(f -> f.FloatValue)
.toArray(Float[]::new);
那很容易。我们来试试二维数组。
// 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)'但不能使用'toArray(float[]::new)'?
办公室里流传的说法是,'float[]::new'调用是不合法的,因为你不能在原始类型上调用'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 };
所以,我的半猜测是从IntFunction推断出某种类型,在二维数组中运作但在一维数组中不起作用。但是,“可能”会有用吗?