7

Is possible to pass parametres using method reference? For example, I have to create a TreeMap but using reverseOrder(). Does something like TreeMap::new(reverseOrder()) exist?

Vincenzo Cosi
  • 173
  • 1
  • 12
  • 2
    A method reference is a _reference to an existing method_. If there is no existing method that does exactly what you want, either write such a method (and then capture a reference to it), or use a lambda whose body does what you want. – Brian Goetz Jul 03 '17 at 21:05
  • Also [External argument to method reference in Java 8](https://stackoverflow.com/questions/38697939/external-argument-to-method-reference-in-java-8) and probably [a lot more](https://stackoverflow.com/search?q=parameters+%22method+reference%22) – Didier L Jul 05 '17 at 19:41

4 Answers4

10

No, you can't do it with a method reference.

You can use lambda expressions instead:

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

or

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

if you are using this expression in a context where the compiler can infer the element type of the TreeMap.

Eran
  • 387,369
  • 54
  • 702
  • 768
6

You need a lambda expression for that... you are probably thinking about a Supplier:

() -> new TreeMap<>(Comparator.reverseOrder())
Eugene
  • 117,005
  • 15
  • 201
  • 306
2

You can't have method references with arguments in Java. You must use a lambda expression instead:

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

But if, for whatever reason, you want/need to use a method reference anyways, here's a way to do it with a helper method:

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());
fps
  • 33,623
  • 8
  • 55
  • 110
1

This is not supported by method references themselves (today), but there are many cases where method references can be used with parameters using Eclipse Collections APIs. Take the following example:

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

Here I compare using the JDK's Map.computeIfAbsent() method which takes a Function and is passed the key as a parameter, and Eclipse Collections' MutableMap.getIfAbsentPutWith() method which also takes a Function and is passed an additional parameter. In the JDK example, I have to use a lambda. In the EC example I am able to use the TreeSet::new constructor reference and specify Comparator.<String>reverseOrder() as the parameter I want passed to it.

There are many *With methods available in Eclipse Collections (e.g. selectWith, rejectWith, collectWith, detectWith, anySatisfyWith etc.). These methods increase the total number of places that can be used with method references in Java 8.

You will find examples of method references used with parameters in the Eclipse Collections Katas.

Company Kata -> Exercise 2 Test
Pet Kata -> Exercise 2 Test

Note: I am a committer for Eclipse Collections.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44