如何使用 Collectors 制作 Map of Map

我被阻止使用Java 函数式编程来构建地图。在我的用例中,这只是一个例子,我想构建一个Map<Integer, Map<Integer, List<Person>>>从List<Person>.


第一步很简单:我首先构建一个Map<Integer, List<person>>.


然后我想添加一个新的分组级别,以便生成一个新的 Map : Map<Integer, Map<Integer, List<person>>>。


重点是:如何正确使用所有 Collectors 功能(groupingBy、映射,也许还有其他功能)来添加新的分组级别?我所有的尝试都失败了:编译器总是告诉我我提供的所有函数都不符合它的预期。


这是代码,简要地说:


首先是一个 Person 类,然后是一个快速构建 List 的方法:


public class Person {


  private long id;

  privae String firstName;

  private String lastName;

  private Date birthDate;

  private int alea;

  ...

此方法(位于 DataBuilder 类中)仅构建一个 Person 列表以向 Main 类提供数据:


public List<Person> getPersons() {


        List<Person> persons = new ArrayList<>();

        Supplier<Person> person = Person::new;


        for (int cpt = 0; cpt < 10; cpt++) {

            Person p = person.get();

            p.setId(cpt);

            p.setFirstName("fn" + cpt);

            p.setLastName("ln" + cpt);

            p.setBirthDate(new Date(119, cpt, 10 + cpt));

            p.setAlea(cpt % 2);

            persons.add(p);

        }


        return persons;


    }

在 Main 中,构建第一层 Map 不是问题:


public static void main(String[] args) {


    DataBuilder db = new DataBuilder();


    List<Person> persons = db.getPersons();


    Map<Integer, List<Person>> mapAleaPerson = persons.stream()

                .collect(Collectors.groupingBy(Person::getAlea,

                        Collectors.mapping(p -> p, Collectors.toList())));


        mapAleaPerson.forEach((k,v) -> System.out.printf("%n%s contains %s%n", k, v));

结果在控制台中正常:


0 contains [Person [id=0, firstName=fn0, lastName=ln0, alea=0], Person [id=2, firstName=fn2, lastName=ln2, alea=0], Person [id=4, firstName=fn4, lastName=ln4, alea=0], Person [id=6, firstName=fn6, lastName=ln6, alea=0], Person [id=8, firstName=fn8, lastName=ln8, alea=0]]


现在我想添加一个新的分组级别。我选择了 BirthDate 的年份,这是 Person 对象的另一个属性。



每次编译器都会因为不兼容的 Function 类型而返回错误。


我发现添加新分组级别的唯一方法是使用旧的 Java 代码和外部循环在 Map 的 Map 中添加和分组数据。


在旧 Java 中嵌入 FP 令人失望!!


有人知道用纯 FP 做所有这些吗?



真正令人惊讶的是,groupingBy与构建第一个 Map 本身的方式相比,嵌套语句的简单性。


为什么我们不再需要指定mappingandCollectors.toList()了?


慕后森
浏览 184回答 1
1回答

宝慕林4294392

使用嵌套groupingBy:Map<Integer,Map<Integer,List<Person>>>&nbsp;mapByYearThenAleaPerson&nbsp;=&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;persons.stream() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.collect(Collectors.groupingBy(p&nbsp;->&nbsp;p.getBirthDate().getYear(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collectors.groupingBy(Person::getAlea)));
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java