Потоковый фильтр на пользовательских объектах Многомерный массив заданного диапазона - PullRequest
0 голосов
/ 18 октября 2018

В последние пару дней я попробовал Java 8 и лямбда-выражения.Вещи понятнее, четче и интереснее в реализации, однако я был озадачен тем, как я могу перебирать многомерный массив заданного диапазона, чтобы найти первое вхождение ненулевого элемента.Например, это мой массив:

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

Как следует из комментария, я пытаюсь найти первое вхождение или ненулевой объект между, скажем,

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 голосов
/ 18 октября 2018

Мы можем сделать это, используя следующий синтаксис:

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);

Здесь мы преобразуем 2D-массив в list, используя flatMap, а затем используем subList, чтобы указать начало и конецИндекс, который вы хотите найти.

Чтобы указать диапазон, вам нужно передать значения в subList(...)

0 голосов
/ 18 октября 2018

Хотя ответ Николаса К хорош для горизонтальных срезов, он не работает для вертикальных срезов.Вот ответ, который делает именно то, что хотел ОП.Просто чтобы прояснить, я написал традиционный (использующий для циклов) способ сделать это, чтобы подтвердить, что это то, что ОП намеревался сделать.Затем я сделал это с помощью потоков.Работает как для горизонтальных, так и для вертикальных срезов.

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");
}
0 голосов
/ 18 октября 2018
MyObject obj = Arrays.stream(array)
        .flatMap(Arrays::stream)
        .filter(Objects::nonNull)
        .findFirst()
        .orElse(null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...