2

As part of arbitrary method references:

Why this is allowed?

Predicate<String> p1 = String::isEmpty;

And why this is not allowed?

BiConsumer<HashMap<String,Integer>, Integer> b1 = HashMap<String,Integer>::put;
2
  • Do you mean now or not? Commented Mar 26, 2017 at 1:31
  • Understood, because in the above case the arguments for put cannot be inferred. This will work BiConsumer<HashSet<Integer>, Integer> b1 = HashSet<Integer>::add; Commented Mar 26, 2017 at 1:35

2 Answers 2

2

In your first example, you're creating a Predicate which takes one String as an input. This matches String.isEmpty() which does not take any arguments. The predicate only operates on the string instance.

As for the second example, let's examine the put method:

public V put(K key, V value)

Since you're using a HashMap<String, Integer>, this would be

public Integer put(String key, Integer value)

As you can see, the method itself is expecting two arguments. Since you want to pass this as a method reference, it also needs the HashMap<String, Integer> in addition to the two arguments.

BiConsumer<HashMap<String, Integer>, Integer> b1 = HashMap<String, Integer>::put;

Over here, you've correctly marked the first generic type argument as HashMap<String, Integer>, but you're missing the String argument which the put method needs. Unfortunately, there is no TriConsumer, but you can easily define your own interface for it:

@FunctionalInterface
public interface TriConsumer<T, U, V> {
 void accept(T t, U u, V v);
}

The @FunctionalInterface annotation is not needed, but it communicates the intent to the reader that this interface can be used as an assignment target for a lambda expression or method reference.

Now you can assign the reference to put:

TriConsumer<HashMap<String, Integer>, String, Integer> consumer = HashMap<String, Integer>::put;
HashMap<String, Integer> map = new HashMap<>();
consumer.accept(map, "Key", 123);
System.out.println(map.get("Key")); // prints 123
answered Mar 26, 2017 at 1:36
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for explaining it so nicely!
@VijayNarayanan I'm glad I could help! Be sure to take a look at Bohemian's answer as well, his example shows how you can assign a reference to a method of a particular object.
1

The basic problem is that put() is not a typed method - one where the type has method scope and can be inferred, it's a generic instance method - one that takes its type from the type of the instance.

Also, you have a mismatch with the type of the method reference and its generic parameters. I have assumed you meant BiFunction, not BiConsumer.

Let's look at what does work:

HashMap<String, Integer> instance = new HashMap<>();
BiFunction<String, Integer, Integer> b1 = instance::put;

If you really meant BiConsumer, this works too:

BiConsumer<String, Integer> b1 = instance::put;

As I've said, because the method takes its types from the instance, so you need a typed instance.

answered Mar 26, 2017 at 1:40

1 Comment

Thank you so much for your explanation!

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.