如何使用流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
的类(你可以使用通用的Tuple
或Pair
)
这些是步骤:
对于每个人,请记录该人的每个电话号码。 对于每个电话号码,创建一个新的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));