4

I have a collection of Long, and for a reason I need to create a map from this collection, which has the elements of the collection as keys, and 1 predefined Enum as value (all keys have the same value).

I am trying to achieve this with Streams, like below:

private Map<Long, Marker> mapMarker(Collection<Long> ids, Marker marker) {
    return ids.stream().collect(Collectors.toMap(Function.identity(), marker));
}

Compiler failed with this error:

no instance(s) of type variable(s) T, U exist so that Marker conforms to Function<? super T, ? extends U>

Could someone please explain to me why would it fails? Is there anyway to get the expected result with Streams?

GBlodgett
  • 12,704
  • 4
  • 31
  • 45
Kate Le
  • 43
  • 4

2 Answers2

3

If Marker is the enum you want to map against ll the keys in ids, you can do it as:

return ids.stream().collect(Collectors.toMap(Function.identity(), id -> marker));

You were quite close, just that id -> marker is a Function as expected for Collectors.toMap

Naman
  • 27,789
  • 26
  • 218
  • 353
2

The parameters to Collectors.toMap should be functions that convert the input to your desired output. You can use a placeholder variable (such as i) to represent your input. For example, for the identity function, take input i and return i. For mapping every item to marker, take input i and return marker:

private Map<Long, Marker> mapMarker(Collection<Long> ids, Marker marker) {
    return ids
            .stream()
            .collect(Collectors.toMap(i -> i, i -> marker));
}
nbrooks
  • 18,126
  • 5
  • 54
  • 66
  • quite close, just that `i->i` is identity :) – Naman Dec 04 '18 at 05:21
  • @nullpointer does that mean that using `Function.identity()` has some practical advantage over using the lambda `i -> i`? (other than readability, that is...) – ernest_k Dec 04 '18 at 05:23
  • 1
    They're not exactly the same, but [close enough](https://stackoverflow.com/questions/28032827/java-8-lambdas-function-identity-or-t-t). I find this more readable, but also found it helpful to illustrate how a "Function" worked in this case. Mostly a matter of preference though. – nbrooks Dec 04 '18 at 05:25
  • @nbrooks thanks for sharing that, I would wonder who apart from Holger could drive those differences. – Naman Dec 04 '18 at 05:26
  • 1
    Seriously though, I don't see there is any way that is clearer than `i -> i`. For someone who isn't a native English speaker, `Function.identify()` will cause them to read the Javadoc to be very sure it does the right thing. – Jai Dec 04 '18 at 05:28
  • 1
    @Jai everyone is free to use whatever they think is more readable, but still, even if you’re not a native English speaker, it’s recommended to know the meaning of certain words (after all, the Javadoc is in English too), just like the keywords of the Java language, which are also English words. The term *identity* is too important to miss it, e.g. it also relates to [identity value](https://stackoverflow.com/a/32867283/2711488), but not to confuse with an object’s identity… – Holger Dec 04 '18 at 08:48