user9347049
user9347049

Reputation: 2055

Collecting a List of objects into a LinkedHashMap with Java 8

I have a list of Profile objects List<Profile> list.

Which I need to convert into a LinkedHashMap<String, String>.

Where object Profile is consisted of:

public class Profile {
    private String profileId;
    private String firstName;
    private String lastName;
}

I have tried the following:

Map<String, String> map = list.stream()
    .collect(Collectors.toMap(Profile::getFirstName, 
                              Profile::getLastName));

But it did not work, I'm getting a compilation error:

Incompatible parameter types in method reference expression

Upvotes: 0

Views: 2146

Answers (1)

Alexander Ivanchenko
Alexander Ivanchenko

Reputation: 28978

Incompatible parameter types in method reference expression

Make sure that you're not using a list of row type as a stream source. I.e. check if the generic type parameter is missing: List list (it has to be List<Profile> list), otherwise all elements of the list as being of type Object and methods from the Profile class would not be accessible.


Collecting into a LinkedHashMap

By default, toMap provides you with a general purpose implementation of the Map (for now it's HashMap but it might change in the future).

In order to collect stream elements into a particular implementation of the Map interface, you need to use a flavor of Collectors.toMap() that expects four arguments:

  • keyMapper - a mapping function to produce keys,
  • valueMapper - a mapping function to produce values,
  • mergeFunction - function that is meant to resolve collisions between value associated with the same key,
  • mapFactory - a supplier providing a new empty Map into which the results will be inserted.

In the code below, mergeFunction isn't doing anything useful, it just has to be present in order to utilize the version of toMap() that allows to specify the mapFactory.

Map<String, String> map = list.stream()
        .collect(Collectors.toMap(
            Profile::getFirstName,
            Profile::getLastName,
            (left, right) -> left,
            LinkedHashMap::new
        ));

Note if there could be cases when more than one value gets associated with the same key, you need either to provide a proper implementation of mergeFunction (to peek a particular value or aggregate values, etc.), or use groupingBy() as a collector, which will allow to preserve all values associated with a particular key.

Upvotes: 3

Related Questions