【问题标题】:Java Intstream get the index of a multidimensional array with null valueJava Intstream 获取具有空值的多维数组的索引
【发布时间】:2020-09-12 21:01:43
【问题描述】:

Java Instream 我需要具有空值的二维数组中的元素索引。我可以使用 对于我在下面做的一维数组,它起作用了:

  IntStream.range(0, myArr.length)
                .filter(x -> myArr[x] == null)
                .findFirst()
                .orElse(-1);

我可以使用 Streams over Arrays 和 flatmap 获取对象,但我的目的是获取 ij 的值,其中 myArr[i][j] 为空。

【问题讨论】:

  • 由于 java 中没有本地元组类型,如果不创建自己的 intTuple 类型,您将无法完成此操作。但是即使那样,流解决方案也必须创建许多对象,我建议只使用嵌套的 for 循环来完成它
  • 正如 Ackdari 所说,如果您想为各种二维数组执行此操作,则需要创建自己的IntTuple,但如果您只是处理矩形二维数组,即每个子数组有相同的长度,那么你可以做一些数学来计算出索引。

标签: java functional-programming java-stream


【解决方案1】:

您可以使用一个long 值来携带两个int 值:

long both = LongStream.range(0, array.length)
    .flatMap(i -> LongStream.range(0, array[(int)i].length).map(j -> j << 32 | i))
    .filter(l -> array[(int)l][(int)(l>>32)] == null)
    .findFirst().orElse(-1);

int j = (int) (both >> 32), i = (int)both;

if(j >= 0) {
    System.out.println("found ("+i+", "+j+")  "+array[i][j]);
}

但这并不比例如简单

int i, j;
search: {
    for(i = 0; i < array.length; i++) {
        var sub = array[i];
        for(j = 0; j < sub.length; j++)
            if(sub[j] == null) break search;
    }
    j = -1;
}

if(j >= 0) {
    System.out.println("found ("+i+", "+j+")  "+array[i][j]);
}

【讨论】:

  • 确实,有时简单是优先考虑的...... :) 感谢您添加另一个观点......
【解决方案2】:

您可以使用Stream.iterateflatMap 将值为null 的所有索引放在SimpleEntry 中,其中键是第一个索引,值是第二个索引:

 Integer[][] integers = {{1, 2, 3, 6}, {4, 5, 6}, {7, 8, null, 11}};
 List<SimpleEntry<Integer, Integer>> collect = 
            Stream.iterate(0, (i) -> i < integers.length, (i) -> ++i)
                .flatMap(i -> IntStream.range(0, integers[i].length)
                      .filter(j -> integers[i][j] == null)
                      .mapToObj(j -> new SimpleEntry<Integer, Integer>(i, j))) 
               .collect(Collectors.toList());

 System.out.println(collect);

那么对于collect 列表中的所有条目integers[entry.getKey()][entry.getValue()] == nulltrue

编辑: 问题本身是微不足道的,唯一要做的决定是应该使用什么容器来存储索引。这是Integerarrays 的“自然”解决方案:

    List<Integer[]> collect1 = new ArrayList<>();
    for (int i = 0; i < integers.length; i++){
        for (int j = 0; j < integers[i].length; j++){
            if (integers[i][j] == null){
                collect1.add(new Integer[]{i, j});
            }
        }
    }

    collect1.forEach(arr -> System.out.println("null at " +arr[0] + "," + arr[1]));

【讨论】:

  • 是的,我的意思是它更像是一种解决方法,我在想在 java 中是否有更自然的解决方案来解决这个问题..
  • 在 java 中有一个使用双循环的自然解决方案,但这就是您可以在 java 中使用流而不使用自定义 Tuple 类的方法。
猜你喜欢
  • 2018-03-13
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 2013-08-14
相关资源
最近更新 更多