параметры в справочнике по методу

Можно ли передать параметры, используя ссылку на метод? Например, мне нужно создать TreeMap, но используя reverseOrder(). Существует ли что-то вроде TreeMap::new(reverseOrder())?


person Vincenzo Cosi    schedule 02.07.2017    source источник
comment
Ссылка на метод — это ссылка на существующий метод. Если нет существующего метода, который делает именно то, что вы хотите, либо напишите такой метод (и затем зафиксируйте ссылку на него), либо используйте лямбду, тело которой делает то, что вы хотите.   -  person Brian Goetz    schedule 04.07.2017
comment
Также Внешний аргумент для ссылки на метод в Java 8 и, возможно, многое другое   -  person Didier L    schedule 05.07.2017


Ответы (4)


Нет, вы не можете сделать это со ссылкой на метод.

Вместо этого вы можете использовать лямбда-выражения:

() -> new TreeMap<TheRelevantType>(reverseOrder())

or

() -> new TreeMap<>(reverseOrder())

если вы используете это выражение в контексте, где компилятор может вывести тип элемента TreeMap.

person Eran    schedule 02.07.2017
comment
Сырые типы, правда? - person ZhekaKozlov; 02.07.2017
comment
@ZhekaKozlov Хороший вопрос, но, не зная контекста, я не знал, какой тип элемента использовать. - person Eran; 02.07.2017
comment
@Eran нет контекста, это была общая ситуация - person Vincenzo Cosi; 02.07.2017

Для этого вам нужно лямбда-выражение... вы, вероятно, думаете о Supplier:

() -> new TreeMap<>(Comparator.reverseOrder())
person Eugene    schedule 02.07.2017
comment
Спасибо, я представлял, что это невозможно сделать - person Vincenzo Cosi; 02.07.2017

В Java не может быть ссылок на методы с аргументами. Вместо этого вы должны использовать лямбда-выражение:

Supplier<Map<String, String>> factory = () ->
        new TreeMap<>(Comparator.reverseOrder());

Но если по какой-либо причине вы все равно хотите/должны использовать ссылку на метод, вот способ сделать это с помощью вспомогательного метода:

public static <T, U> Supplier<T> withArg(
        Function<? super U, ? extends T> methodRef,
        U arg) {
    return () -> methodRef.apply(arg);
}

Supplier<Map<String, String>> factory = withArg(
        TreeMap::new, 
        Comparator.<String>reverseOrder());
person fps    schedule 03.07.2017

Это не поддерживается самими ссылками на методы (сегодня), но во многих случаях ссылки на методы можно использовать с параметрами, используя Коллекции Eclipse API. Возьмем следующий пример:

Map<String, TreeSet<String>> jdkMap = new HashMap<>();
jdkMap.put("one", new TreeSet<>(Comparator.reverseOrder()));
jdkMap.computeIfAbsent("two", key -> new TreeSet<>(Comparator.reverseOrder()));

MutableMap<String, TreeSet<String>> ecMap =
        Maps.mutable.with("one", new TreeSet<>(Comparator.reverseOrder()));
ecMap.getIfAbsentPutWith("two", TreeSet::new, Comparator.<String>reverseOrder());

Assert.assertEquals(jdkMap, ecMap);

Здесь я сравниваю использование метода Map.computeIfAbsent() из JDK, который принимает Function и передает ключ в качестве параметра, и метод MutableMap.getIfAbsentPutWith() из Eclipse Collections, который также принимает Function и передает дополнительный параметр. В примере с JDK я должен использовать лямбду. В примере EC я могу использовать ссылку на конструктор TreeSet::new и указать Comparator.<String>reverseOrder() в качестве параметра, который я хочу ему передать.

В Eclipse Collections доступно множество методов *With (например, selectWith, rejectWith, collectWith, detectWith, anySatisfyWith и т. д.). Эти методы увеличивают общее количество мест, которые можно использовать со ссылками на методы в Java 8.

Вы найдете примеры ссылок на методы, используемые с параметрами, в каталогах коллекций Eclipse.

Компания Kata -> Тест упражнения 2
Pet Kata -> Тест упражнения 2

Примечание. Я коммиттер Eclipse Collections.

person Donald Raab    schedule 03.07.2017