java - 在 Java 8 中使用 Group By 和属性

标签 java lambda java-8 java-stream collectors

package com;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class GroupByDemoInJava8 
{
    public static void main(String args[]) throws IOException
    {
        List<Person> people = new ArrayList<>();  // Date Format is MM/DD/YYYY
        people.add(new Person("John", "London", 21 , "2/1/18"));
        people.add(new Person("Swann", "London", 21 , "3/5/18" ));
        people.add(new Person("Kevin", "London", 23 , "3/12/18"));
        people.add(new Person("Monobo", "Tokyo", 23 , "4/18/18"));
        people.add(new Person("Sam", "Paris", 23 , "7/12/18"));
        people.add(new Person("Nadal", "Paris", 31, "4/2/19")); 
        Map<String,List<Person>> personByCity = new HashMap<>(); 

        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");


        personByCity = people.stream() .collect(Collectors.groupingBy(sdf.parse(Person::getDateOfBirth))); 


         for (Map.Entry<String,List<Person>> entry : personByCity.entrySet()) { 
                System.out.println("Key = " + entry.getKey());
                System.out.println("Value = " + entry.getValue());
        } 

    }
}


class Person
{ 
    private String name; 
    private String city; private int age; private String dateOfBirth;

    public String getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(String dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public Person(String name, String city, int age , String dateOfBirth) 
    { 
        this.name = name; this.city = city; this.age = age;this.dateOfBirth=dateOfBirth;
    }

    public String getName()
    { return name; } 
    public void setName(String name) 
    { this.name = name; } 
    public String getCity() 
    { return city; } 
    public void setCity(String city)
    { this.city = city; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }

    @Override
    public String toString() {
        return "Person [name=" + name + ", city=" + city + ", age=" + age + "]";
    }
}

不幸的是,我收到以下编译错误

  • The method parse(String) in the type DateFormat is not applicable for the arguments (Person::getDateOfBirth)
  • The target type of this expression must be a functional interface

最佳答案

如果是直接方法调用,方法引用运算符用于替换 lambda 表达式,但在您的情况下,您尝试执行 groupingBy基于 sdf.parse 的结果

Method References

You use lambda expressions to create anonymous methods. Sometimes, however, a lambda expression does nothing but call an existing method. In those cases, it's often clearer to refer to the existing method by name. Method references enable you to do this; they are compact, easy-to-read lambda expressions for methods that already have a name.

还有parse方法来自 SimpleDateFormat抛出ParseException除了返回 java.util.Date 之外,您是否需要处理它所以你需要将返回类型更改为 Map<Date,List<Person>>

public Date parse(String source) throws ParseException

如果你想使用 SimpleDateFormat 还是这样你需要处理异常

 Map<Date,List<Person>> personByCity = people.stream() 
                      .collect(Collectors.groupingBy(person->{
                          try {
                             return sdf.parse(person.getDateOfBirth());
                           }
                           catch(ParseException ex){
                                //log error
                              }
                            return new Date();
                         });

我更喜欢的推荐方法是使用 LocalDate通过使用DateTimeFormatter

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yy");

 Map<LocalDate,List<Person>> personByCity = people.stream() 
                      .collect(Collectors.groupingBy(person->LocalDate.parse(person.getDateOfBirth(),formatter)); 

注意您输入的日期字符串 "2/1/18"和格式模式"MM/dd/yy"两者都是有效的,但返回类型会根据实现而改变,下面是示例

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yy");

LocalDate date = LocalDate.parse("02/01/18", formatter);

System.out.println(date);      //2018-02-01

SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yy");

Date d = sdf.parse("02/01/18");

System.out.println(d);       //Thu Feb 01 00:00:00 CST 2018

关于java - 在 Java 8 中使用 Group By 和属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57214116/

相关文章:

C# 到 Lambda - 计算小数位数/第一位有效小数

java - Java 8的回调机制

java - 如何使用 POI 库从 Excel 中读取筛选后的行

java - 检查 Object 是否是 List<Object> 的实例

java - 如何在 java 中有效地处理数百万元组的集合?

java - 获取绝对 java.nio.Path

java - 从文件 Java 8 中读取行并在两者之间中断的最佳方法

java - 如何在不实际运行 Java 类的情况下分析它的性能?

java - Java 流阶段是顺序的吗?

c# - C# 6.0 语法错误