Собирать дополнительные предметы

Учитывая таблицу Guava Immutable, мне нужно обработать все ячейки и отфильтровать некоторые ячейки на основе некоторого результата сопоставления, который возвращает Java Optional,

  immutbleTable.cellSet()
            .parallelStream()
                .map(cell -> processAndGetOptionalResult(cell))
                .filter(cell -> cell.isPresent())
                .map(cell -> cell.get())
                .collect(Collector.of(
                        ImmutableTable.Builder::new,
                        ImmutableTable.Builder::put,
                        (l, r) -> l.putAll(r.build()),
                        ImmutableTable.Builder<String,String,String>::build)
            );
    }

Есть ли лучший способ добиться этого? Есть ли способ, которым я могу удалить "map(cell -> cell.get())" и собрать cell.get () через сам аккумулятор?

2 ответа

Решение

Вы можете интегрировать обработку Optional в Collector:

resultTable = immutableTable.cellSet().parallelStream()
    .map(cell -> processAndGetOptionalResult(cell))
    .collect(Collector.of(
            ImmutableTable.Builder::new,
            (b,o) -> o.ifPresent(b::put),
            (l, r) -> l.putAll(r.build()),
            ImmutableTable.Builder<String,String,String>::build)
    );

Это работает гладко, так как функция-накопитель представляет действие, и выполнение действия (если оно не пустое) является одним из канонических вариантов использования для Optional, в отличие от isPresent-get последовательность.

Помимо использования ссылок на методы:

immutbleTable.cellSet()
        .parallelStream()
            .map(this::processAndGetOptionalResult)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .collect(Collector.of(
                    ImmutableTable.Builder::new,
                    ImmutableTable.Builder::put,
                    (l, r) -> l.putAll(r.build()),
                    ImmutableTable.Builder<String,String,String>::build)
        );
}

Ответ - нет - в текущем (JDK 8) API нет лучшего способа добиться этого. В JDK 9 Optional буду иметь .stream() метод, который позволит использовать одну операцию - flatMap:

immutbleTable.cellSet()
        .parallelStream()
            .map(this::processAndGetOptionalResult)
            .flatMap(Optional::stream)
            .collect(Collector.of(
                    ImmutableTable.Builder::new,
                    ImmutableTable.Builder::put,
                    (l, r) -> l.putAll(r.build()),
                    ImmutableTable.Builder<String,String,String>::build)
        );
}

Для более подробной информации смотрите этот ответ.

Другие вопросы по тегам