如何使用流API在Java 8中映射?

好的,所以我有一个List 。 每个Person都有一个List ,它是该人拥有的电话号码列表。

所以这是基本结构:

 public class Person { private String name; private List phoneNumbers; // constructors and accessor methods } 

我想创建一个Map ,其中key是该人拥有的每个电话号码,值是实际的人。

所以要更好地解释。 如果我有这个List

 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 list = new ArrayList(); list.add(bob); list.add(john); 

我调用了这个方法。 它会给我以下Map

 Map 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); 

我想知道如何使用stream API实现这一点,因为我已经知道如何使用for循环等。

如果你有一个名为persons名单和一个名为PhoneNumberAndPerson的类(你可以使用通用的TuplePair

这些是步骤:

对于每个人,请记录该人的每个电话号码。 对于每个电话号码,创建一个新的PhoneNumberAndPerson实例并将其添加到列表中。 使用flatMap制作所有这些较小列表的单个列表。 要从这个列表中创建一个Map ,你需要提供一个函数来从PhoneNumberAndPerson提取一个键,另一个函数从同一个PhoneNumberAndPerson提取一个Person

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

没有额外的类和预创建映射:

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

如果没有创建其他类,我会选择以下内容:

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

编辑:正如Simon所建议的那样,你可以使用collect方法,但如果你想使用你提供的类创建一个地图,使用一个更简单的类(不使用List但只是一个普通的String来存储),这可能会很棘手你可以简单地调用下面的代码来返回一个Map

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