java - 如何使用 Java-8 Streams 将 n 维数组映射到另一种类型?

标签 java java-8 java-stream biginteger bigdecimal

我有一个 double[][],我想将它转换为 BigDecimal[][]。我可以执行以下操作:

public static BigDecimal[][] convert(double[][] arr1){
    BigDecimal[][] arr2 = new BigDecimal[arr1.length][arr1[0].length];
    for(int i = 0; i < arr1.length; i++){
        for(int j = 0; j < arr1[0].length; j++){
            arr2[i][j] = new BigDecimal(arr1[i][j]);
        }
    }
    return arr2;
}

如何在 Java-8 中使用流执行此操作?

一般来说,给定一个类型为 Foo 的对象,其构造函数接受一个类型为 Bar 的对象,转换 Bar 的最佳方法是什么[][]Foo[][] 使用流? Bar[][][]Foo[][][] 怎么样?

单一维度的转换是直接的。我用于一维数组的代码是:

pubilc static Foo[] convert(Bar[] bars){
    return Arrays.stream(bars).mapToObj(Foo::new).toArray(Foo[]::new); 
}

这如何在二维中实现? 3 维或 4 维呢?是否可以编写一种递归方法,将一种类型的 n 维数组转换为另一种类型的 n 维数组?

最佳答案

直接的方式:

public static BigDecimal[][] convert(double[][] arr1){
    return Arrays.stream(arr1).map(
        r -> Arrays.stream(r).mapToObj(BigDecimal::new).toArray(BigDecimal[]::new)
    ).toArray(BigDecimal[][]::new);
}

这会创建一个 Stream<double[]>从输入数组中映射每个 double[]BigDecimal[] (通过创建一个 DoubleStream 并将每个 double 映射到一个新的 BigDecimal )并最终生成一个 BigDecimal[][]该流的数组。


将其扩展到 3D 数组是相同的逻辑:我们创建一个 Stream<double[][]>输入数组的每个 double[][] 转换到 BigDecimal[][]通过前面的代码并将其转换回数组。

public static BigDecimal[][][] convert(double[][][] arr1){
    return Arrays.stream(arr1).map(r -> convert(r)).toArray(BigDecimal[][][]::new);
}

感谢Holger ,这纠正了我最初的方法,这可以扩展到 n具有以下内容的维数组。限制是您需要特别注意原始数组。

public static <T> T[] convert(
    Object[] array, Function<Object, Object> mapper, Class<T[]> returnClass) {

    Class componentType = returnClass.getComponentType();
    return Arrays.stream(array)
                 .map(array instanceof Object[][]?
                      r -> convert((Object[])r, mapper, componentType): mapper::apply)
                 .toArray(i -> returnClass.cast(Array.newInstance(componentType, i)));
}

(请注意,您可能需要明确地导入 java.lang.reflect.Array)。用

测试
public static void main(String[] args) {
    Double[][] d = { { 0.1 }, { }, { 0.2, 0.3 } };
    BigDecimal[][] bd=convert(d, v -> new BigDecimal((Double) v), BigDecimal[][].class);
    System.out.println(Arrays.deepToString(bd));
}

将它与原始数组一起使用时,您必须使用映射器函数处理最后一个维度(例如 double[] ),因为一维原始数组不是 Object[] 的实例。并且不能用通用代码处理。一个示例用法是

public static void main(String[] args) {
    double[][][] da= { {{ 0.1 }, { }}, {{ 0.2, 0.3 }, { 0.4 }} };
    BigDecimal[][][] bd=convert(da,
      v -> Arrays.stream((double[])v).mapToObj(BigDecimal::new).toArray(BigDecimal[]::new),
      BigDecimal[][][].class);
    System.out.println(Arrays.deepToString(bd));
}

关于java - 如何使用 Java-8 Streams 将 n 维数组映射到另一种类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35186603/

相关文章:

java - 通过组合多个流的结果来创建流

java - java中删除字符串中的字符

java - 泛型和 instanceof - java

java - 如何使用 JAXB 编码消除元素/属性中自动生成的命名空间前缀

java - 删除Java中重载的方法

java 8 streams 如何将 Map<String, List<Strings>> 转换为 List<String> 将所有字符串值?

java - 转换值的方法背后的基本原理

java-8 - Mockito 无法模拟此类 : interface

java - 用 lambda 表达式替换匿名函数

java - 可选字段流返回值