How do I map this in Java 8 using the stream API?

好久不见. 提交于 2019-12-22 08:06:13

问题


Ok, so I have a List<Person>. and each Person has a List<String> that is a list of phone numbers that that person owns.

So this is the basic structure:

public class Person {

    private String name;
    private List<String> phoneNumbers;

    // constructors and accessor methods

}

I would like to create a Map<String, Person> where the key is each phone number that the person owns, and the value is the actual person.

So to explain better. If I had this List<Person>:

Person bob = new Person("Bob");
bob.getPhoneNumbers().add("555-1738");
bob.getPhoneNumbers().add("555-1218");

Person john = new Person("John");
john.getPhoneNumbers().add("518-3718");
john.getPhoneNumbers().add("518-3115");
john.getPhoneNumbers().add("519-1987");

List<Person> list = new ArrayList<>();
list.add(bob);
list.add(john);

and I invoked this method. It would give me the following Map<String, Person>

Map<String, Person> map = new HashMap<>();
map.put("555-1738", bob);
map.put("555-1218", bob);

map.put("518-3718", john);
map.put("518-3115", john);
map.put("519-1987", john);

I would like to know how to achieve this using the stream API, as I already know how I would do it using for loops and such.


回答1:


If you have list of persons called persons and a class called PhoneNumberAndPerson (you could use a generic Tuple or Pair instead)

These are the steps:

For each person, take each phone number of that person. For each of those phone numbers, create a new instance of PhoneNumberAndPerson and add that to a list. Use flatMap to make one single list of all these smaller lists. To make a Map out of this list you supply one function to extract a key from a PhoneNumberAndPerson and another function to extract a Person from that same PhoneNumberAndPerson.

persons.stream()
    .flatMap(person -> person.getPhoneNumbers().stream().map(phoneNumber -> new PhoneNumberAndPerson(phoneNumber, person)))
    .collect(Collectors.toMap(pp -> pp.getPhoneNumber(), pp -> pp.getPerson()));



回答2:


Without additional class and pre-creating map:

Map<String, Person> result = list.stream().collect(HashMap::new,
     (map, p) -> p.getPhoneNumbers().forEach(phone -> map.put(phone, p)), HashMap::putAll);



回答3:


Without creating other classes i'd go for something like this:

    Map<String, String> map = new HashMap<>();
    list.stream().forEach(p -> p.getPhoneNumbers().forEach(n -> map.put(n, p.getName())));

Edit: As suggested by Simon, you can use the collect method, but it can be tricky if you want to create a map using the class that you provided, with a simpler class ( without using List but just a plain String in order to store the number) you can simply call the code below that returns a Map

list.stream().collect(Collectors.toMap(Person::getPhoneNumber, Person::getName));


来源:https://stackoverflow.com/questions/36560344/how-do-i-map-this-in-java-8-using-the-stream-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!