Подтвердить что ты не робот

Где находится потребитель Java 8 с несколькими аргументами?

Например, в .Net, который предоставляет несколько реализаций делегата Action (эквивалентного функциональному интерфейсу Java Consumer) с различным количеством и типом аргументов, я ожидал, что Java 8 предоставляет некоторый способ указания Consumer с несколькими аргументами разных типов.

Я знаю, что в Java мы не можем определить разные типы с тем же именем, которые просто отличаются параметрами родового типа, но были бы неплохие альтернативы для предоставления многопараметрических Consumer.

Есть ли простой способ сделать это, что не требует определения нового функционального интерфейса?

4b9b3361

Ответ 1

Для 3 и более аргументов вы можете использовать функции curried (http://en.wikipedia.org/wiki/Currying) с последним потребителем:

Function<Double, Function<Integer, Consumer<String>>> f = d -> i -> s -> {
            System.out.println("" + d+ ";" + i+ ";" + s); 
        };
f.apply(1.0).apply(2).accept("s");

Выход:

1.0;2;s

Достаточно иметь функцию одного аргумента для выражения функции любого числа аргументов: http://en.wikipedia.org/wiki/Currying#Mathematical_view

Ответ 2

По умолчанию вы ограничены только java.util.function.Consumer и java.util.function.BiConsumer. Их достаточно для текущего API потоковой передачи Java. Но вы можете создавать свои собственные функциональные интерфейсы, которые будут получать столько аргументов, сколько вам захотят, и использовать их в своих собственных API-интерфейсах.

Ответ 3

Есть ли простой способ сделать это, что не требует определения нового функционального интерфейса?

Объект может содержать любое количество других объектов. API Streams предназначен для потоковой передачи всего одного объекта за раз, и если вам нужно больше, вы можете обернуть их в объект, который удерживает их все.

например.

Map<String, Long> map = new HashMap<>();
// each entry has a key and a value as Map.Entry<String, Long>
Map<Long, String> revMap = map.entrySet().stream()
            .collect(groupingBy(Entry::getValue(), HashMap::new, Entry::getKey));

Ответ 4

Довольно легко определить функциональные интерфейсы для себя. В проекте, над которым я сейчас работаю, я нашел несколько случаев, когда передача метода в качестве аргумента позволила мне сохранить мой код красивым и сухим. Вот некоторые функциональные интерфейсы, которые я определил:

@FunctionalInterface
public interface CheckedVoidFunction {
    void apply() throws Exception;
}

@FunctionalInterface
public interface VoidFunction {
    void apply();
}

@FunctionalInterface
public interface SetCategoryMethod {
    void accept(ObservableList<IRegionWithText> list, Document document, String pattern);
}

Вот метод, который принимает такие аргументы:

private void loadAnnotations(String annotationType, VoidFunction afterLoadFunction, List<Path> documentPaths) {

И здесь я называю эти методы различными методами в качестве аргументов:

loadAnnotations(DocumentReader.REDACTION_ANNOTATION_TYPE, this::afterLoadRedactions, documentPaths);
loadAnnotations(DocumentReader.HIGHLIGHT_ANNOTATION_TYPE, this::afterLoadHighlights, documentPaths);

Там могут быть лучшие способы сделать это, но я думал, что поделюсь тем, что было полезно для меня.