为了账号安全,请及时绑定邮箱和手机立即绑定

如何根据日期进行分组并添加其他属性

如何根据日期进行分组并添加其他属性

BIG阳 2023-04-26 10:49:35
我有 Person DTO 有 4 个属性class Person {            private String name;            private String city;            private int age;            private String dateOfBirth;            // Setters and getters }// sample data      personList.add(new Person("Mike", "London", 38, "01/01/1981"));                personList.add(new Person("John", "London", 38, "01/02/1981"));                personList.add(new Person("John", "Bristol",38, "01/06/1981"));                personList.add(new Person("Steve", "Paris",06, "03/07/2013"));我正在尝试根据 dateOfBirth 属性对上述列表中的数据进行分组。(仅考虑月份和年份,日期被忽略)如果用户属于同一月份和年份,则添加年龄,下面的示例输出
查看完整描述

2 回答

?
紫衣仙女

TA贡献1839条经验 获得超15个赞

为了使这个简单,首先我将流式传输List<Person然后将它们收集到Map<String, List<Person>>使用基于Date输出模式的 groupingBy 中outputPattern,因为SimpleDateFormat这是我想使用的遗产LocalDate


 String outDate = LocalDate.parse(p1.getDateOfBirth(),

                                  DateTimeFormatter.ofPattern(patternInput))

                                 .format(DateTimeFormatter.ofPattern(outputPattern)); 

现在将其与groupingBy


 Map<String, List<Person>> groupResult = personList.stream()

            .collect(Collectors.groupingBy(p->LocalDate.parse(p.getDateOfBirth(),

                           DateTimeFormatter.ofPattern(patternInput))

                               .format(DateTimeFormatter.ofPattern(outputPattern))));

现在使用forEach并以所需格式打印输出


  groupResult.forEach((k,v)->System.out.println("Date : "+ k+

        ", Age : " + v.stream().mapToInt(Person::getAge).sum()+

        ", UniqueCityCount : "+v.stream().map(Person::getCity).distinct().count()));

最后输出


Date : Mar-19, Age : 34, UniqueCityCount : 1

Date : Jan-81, Age : 97, UniqueCityCount : 2

您也可以使用YearMonth,但如果您需要自己的格式,它仍然是一回事


  String ym = YearMonth.parse(p1.getDateOfBirth(), 

                  DateTimeFormatter.ofPattern(patternInput))

                  .format(DateTimeFormatter.ofPattern(outputPattern));

输出


Mar-19

按默认年月返回此格式ISO-8601 日历系统中的年月,例如 2007-12。


查看完整回答
反对 回复 2023-04-26
?
慕婉清6462132

TA贡献1804条经验 获得超2个赞

Map< YearMonth , Set < Person > >

对于日期时间工作,您使用的是多年前随着 JSR 310 的采用而被取代的可怕的旧类。您应该改用java.time类。

对于班级中的出生日期成员,请使用数据类型LocalDate。这表示没有时间和时区的日期。

提示:使用ISO 8601字符串将日期时间值序列化为文本。对于仅限日期的值,则为 YYYY-MM-DD。

LocalDate ld = LocalDate.parse( "2019-01-23" ) ;

对于按年-月的聚合,请使用该类YearMonth

YearMonth ym = YearMonth.from( ld ) ;

为什么要将年龄传递给构造函数?您传递生日,因此可以计算年龄。年龄应该通过动态计算经过的年数的 getter 方法返回,从不存储。

此外,您的示例数据毫无意义,年龄与生日不符。

Person p = new Person( "Alice" , "Johnson" , "1981-01-02" ) ;
int age = p.getAge() ;

实施Person::getAge( ZoneId )方法。

确定今天的日期需要时区。对于任何给定时刻,日期在全球范围内因地区而异。

ZoneId z = ZoneId.of( "America/Montreal" ) ;

将区域传递给getAge方法。

public int getAge( ZoneId z ) {

    LocalDate today = LocalDate.now( z ) ;

    Period age = Period.between( p.getBirthDate() , today ) ;

    int years = age.getYears() ;

    return years ;

}

或者,将LocalDate(今天的日期)传递给getAge而不是时区。


将您的地图定义为将年月映射到一组人。


Map< YearMonth , Set< Person > > = new TreeMap<>() ;

对于每个Person对象,获取YearMonth其出生日期。对于每个这样的年月,Person如果尚不存在,则创建一组对象。并将此人添加到集合中。


完成后,循环地图以检索每组人。循环Person该组中的每个对象。计算年龄,求和。


如果您想花哨一点,可以使用流来完成报告年龄和代码。


查看完整回答
反对 回复 2023-04-26
  • 2 回答
  • 0 关注
  • 107 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信