自定义对象上的流过滤器给定范围的多维数组

时间:2018-10-18 02:12:39

标签: java arrays lambda java-8 java-stream

最近几天,我开始尝试使用Java 8和lambda表达式。实施起来事情更加清晰,清晰和有趣,但是我不知道如何在给定范围内对多维数组进行迭代以查找非空元素的首次出现。例如,这是我的数组:

MyObject[][] array = new MyObject[][]; //this array is never full objects are placed at random places

正如评论所暗示的那样,我正在尝试查找假设之间的第一个匹配对象或非null对象

array[0-5][irrelevant] 
       or
array[irrelevent][3-9]

到目前为止我得到的最接近的是:

MyObject obj = Arrays.stream(grid.grid)
                .flatMap(IntStream.range(0,2)) //here it must work for any dimension given any range
                .filter(array -> array != null)
                .findFirst()
                .orElse(null); 

很显然,这不是编译器,因为它不是Integer元素而是自定义对象。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

我们可以使用以下语法:

MyObject findFirst = Arrays.stream(array).flatMap(Arrays::stream)
                       .collect(Collectors.toList())
                       .subList(0, 3) // observe this line
                       .stream()
                       .filter(e -> e != null).findFirst().orElse(null);

在这里,我们使用list将2D数组转换为flatMap,然后使用subList指定要搜索的索引的开始和结束。

要指定范围,您需要将值传递到subList(...)

答案 1 :(得分:1)

尽管Nicholas K的答案适用于水平切片,但不适用于垂直切片。这是一个完全符合OP要求的答案。为了清楚起见,我已经编写了传统的(使用for循环)方法来确认这就是OP打算完成的工作。然后,我已经使用流完成了它。它适用于水平和垂直切片。

public static void main(String[] args) {

    // Sample data
    Object[][] array = new Object[5][10];
    array[1][5] = "this is it";  // This is the first non-null object
    array[4][7] = "wrong one";   // This is another non-null object but not the first one

    // Define range (start=inclusive, end=exclusive)
    int iStart = 0, iEnd = array.length, jStart = 3, jEnd = 9; // array[irrelevant][3-9]
    //int iStart = 1, iEnd = 3, jStart = 0, jEnd = array[0].length; // array[1-3][irrelevant]

    // Doing it the traditional way
    Object firstNonNull = null;
    outerLoop:
    for (int i = iStart; i < iEnd; i++)
        for (int j = jStart; j < jEnd; j++)
            if (array[i][j] != null) {
                firstNonNull = array[i][j];
                break outerLoop;
            }

    assert firstNonNull != null;
    assert firstNonNull.equals("this is it");

    // Doing it with Java 8 Streams
    firstNonNull = Arrays.asList(array)
            .subList(iStart, iEnd)
            .stream()
            .flatMap(row -> Arrays.asList(row)
                    .subList(jStart, jEnd)
                    .stream()
                    .filter(Objects::nonNull))
            .findFirst()
            .orElse(null);

    assert firstNonNull != null;
    assert firstNonNull.equals("this is it");
}

答案 2 :(得分:-1)

MyObject obj = Arrays.stream(array)
        .flatMap(Arrays::stream)
        .filter(Objects::nonNull)
        .findFirst()
        .orElse(null);