4

I tried to follow Java 8 List into Map and try to change Set to Map in one list

Instead of looping (which works)

for (Type t : toSet()) {
    map.put(Pair.of(t, Boolean.TRUE), this::methodAcceptingMap);
}

I tried with solutions as:

toSet().stream()
       .collect(Collectors.toMap(Pair.of(Function.identity(), Boolean.TRUE), 
                                 this::methodAcceptingMap));

But got an error converting:

Type mismatch: cannot convert from Pair<Function<Object,Object>,Boolean> 
to Function<? super T,? extends K>

My map

private Map<Pair<Type, Boolean>, BiConsumer<Pair<Type, Boolean>, Parameters>> map =
      new HashMap<>();
Andronicus
  • 25,419
  • 17
  • 47
  • 88
Ori Marko
  • 56,308
  • 23
  • 131
  • 233

2 Answers2

6

Collectors.toMap takes two functions, and neither of your arguments fits.

You should use:

Map<Pair<Type, Boolean>, BiConsumer<Pair<Type, Boolean>, Parameters>> map =
    set.stream()
       .collect(Collectors.toMap(el -> Pair.of(el, Boolean.TRUE), 
                                 el -> this::methodAcceptingMap));

The expression Pair.of(t, Boolean.TRUE) is simply not of a Function type. And this::methodAcceptingMap could fit the signature of a BiConsumer, but the method requires a Function. So el -> this::methodAcceptingMap should be used as a function that takes a stream element and returns your BiConsumer.

Note that the assignment context (map =) is important in this case. Without it, the target type of these lambda expressions will be missing and compilation will fail.

ernest_k
  • 44,416
  • 5
  • 53
  • 99
1

I don't quite get your example. In for loop you're passing the same lambda for every value. I don't see sense in that. If you really want that, you need to pass obj -> (pair, param) -> this.methodAcceptingMap(pair, param):

toSet().stream().collect(Collectors.toMap(
    obj -> Pair.of(obj, Boolean.TRUE), 
    obj -> (pair, param) -> this.methodAcceptingMap(pair, param)));
Andronicus
  • 25,419
  • 17
  • 47
  • 88
  • Different error `The method toMap(Function super T,? extends K>, Function super T,? extends U>) in the type Collectors is not applicable for the arguments (( obj) -> {}, this::methodAcceptingMap)` – Ori Marko Dec 15 '19 at 07:25
  • I think method is irrelevant for now, but here it's `private void methodAcceptingMap(Pair pair, Parameters parameters)` Last solution give me different error `Lambda expression's signature does not match the signature of the functional interface method apply(? super T)` – Ori Marko Dec 15 '19 at 07:32
  • Different error `Cannot infer type argument(s) for collect(Collector super T,A,R>)` – Ori Marko Dec 15 '19 at 07:41
  • And if you exchange `(pair, param) -> this.methodAcceptingMap(pair, param)` with method refeence, i.e: `this::methodAcceptingMap` – Andronicus Dec 15 '19 at 07:44
  • Same error, can you try reproduce? if needed I'll try to make a minimal example – Ori Marko Dec 15 '19 at 07:46
  • @user7294900 ernest_k asked you to do the same thing and his works? – Andronicus Dec 15 '19 at 08:00
  • It wasn't exact code, now is different and before was different `toSet().stream().collect(Collectors.toMap( obj -> Pair.of(obj, Boolean.TRUE), this::methodAcceptingMap));` – Ori Marko Dec 15 '19 at 08:02
  • ` .collect(Collectors.toMap(el -> Pair.of(el, Boolean.TRUE), el -> this::methodAcceptingMap));` . Whereas my earlier comment: "And if you exchange `(pair, param) -> this.methodAcceptingMap(pair, param)` with method refeence, i.e: `this::methodAcceptingMap`". – Andronicus Dec 15 '19 at 08:03
  • Still didn't work, needed to change to `el -> this::methodAcceptingMap` – Ori Marko Dec 15 '19 at 08:05
  • There is a parameter... I asked to change `(pair, param) -> this.methodAcceptingMap(pair, param)`, not `obj -> (pair, param) -> this.methodAcceptingMap(pair, param)` – Andronicus Dec 15 '19 at 08:06
  • So finally `obj -> this::methodAcceptingMap` – Andronicus Dec 15 '19 at 08:06
  • with also making Pair returning Function as `el -> Pair.of(el, Boolean.TRUE)` – Ori Marko Dec 15 '19 at 08:11
  • @user7294900 and what is it by me? I don't get it... Name of lambda parameter does not matter. I wrote `obj -> Pair.of(obj, Boolean.TRUE)`, you say it should be `el -> Pair.of(el, Boolean.TRUE)`, right? – Andronicus Dec 15 '19 at 08:13
  • This solution is actually correct. You need an assignment or method invocation context for the target types of the lambda expressions to be correctly inferred (so if you just assigned the whole expression to `map`, it'd compile). – ernest_k Dec 15 '19 at 08:21