【问题标题】:Using Group By in Java 8 with Property在 Java 8 中使用 Group By 和属性
【发布时间】:2019-07-26 06:13:38
【问题描述】:
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 + "]";
    }
}

很遗憾,我收到以下编译错误

  • DateFormat 类型中的方法 parse(String) 不适用于参数 (Person::getDateOfBirth)
  • 此表达式的目标类型必须是函数式接口

【问题讨论】:

  • 变量personByCity的名字错误,提示按城市分组。但这当然不是解决方案。我去办公室看看。
  • 我从未见过将日期存储为字符串,或者在每次获取它时转换它。尝试将其转换为施工时间并将其存储为日期。然后将其作为日期获取。那应该可以。

标签: java lambda java-8 java-stream collectors


【解决方案1】:

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

Method References

您使用 lambda 表达式来创建匿名方法。 然而,有时 lambda 表达式只会调用现有方法。在这些情况下,通过名称引用现有方法通常会更清楚。方法引用使您能够做到这一点;它们是紧凑、易于阅读的 lambda 表达式,用于已命名的方法。

还有来自SimpleDateFormatparse 方法抛出ParseException 是否需要处理它,此外它还返回java.util.Date,因此您需要将返回类型更改为Map&lt;Date,List&lt;Person&gt;&gt;

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();
                         });

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

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

【讨论】:

  • person.getDateOfBirth() 是不包含 person 对象方法的对象。
  • 谢谢你的时间,我可以根据日期属性按升序对数据进行排序
【解决方案2】:

首先您说日期的格式为 MM/DD/YYYY,但实际上并非如此。应定义您的数据:

List<Person> people = new ArrayList<>(); // Date Format is MM/DD/YYYY
people.add(new Person("John", "London", 21, "02/01/2018"));
people.add(new Person("Swann", "London", 21, "03/05/2018"));
people.add(new Person("Kevin", "London", 23, "03/12/2018"));
people.add(new Person("Monobo", "Tokyo", 23, "04/18/2018"));
people.add(new Person("Sam", "Paris", 23, "07/12/2018"));
people.add(new Person("Nadal", "Paris", 31, "04/02/2019"));

其次不要使用SimpleDateFormat,它已经过时了,而是使用DateTimeFormatterLocalDatefrom java 1.8:

Map<LocalDate, List<Person>> personByCity = new HashMap<>();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/yyyy");
personByCity = people.stream()
            .collect(Collectors.groupingBy(p -> LocalDate.parse(p.getDateOfBirth(), dtf)));

【讨论】:

  • 谢谢它的作品我们可以使用日期排序吗? , 应首先显示最低日期
  • 在这种情况下考虑支持/接受答案。您能否更具体一点 - 您想在什么基础上对日期进行排序?
猜你喜欢
  • 1970-01-01
  • 2018-01-10
  • 2022-10-12
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
  • 2012-03-10
  • 1970-01-01
相关资源
最近更新 更多