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

我有 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 属性对上述列表中的数据进行分组。(仅考虑月份和年份,日期被忽略)如果用户属于同一月份和年份,则添加年龄,下面的示例输出


BIG阳
浏览 108回答 2
2回答

紫衣仙女

为了使这个简单,首先我将流式传输List<Person然后将它们收集到Map<String, List<Person>>使用基于Date输出模式的 groupingBy 中outputPattern,因为SimpleDateFormat这是我想使用的遗产LocalDate&nbsp;String outDate = LocalDate.parse(p1.getDateOfBirth(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateTimeFormatter.ofPattern(patternInput))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.format(DateTimeFormatter.ofPattern(outputPattern));&nbsp;现在将其与groupingBy&nbsp;Map<String, List<Person>> groupResult = personList.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.groupingBy(p->LocalDate.parse(p.getDateOfBirth(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;DateTimeFormatter.ofPattern(patternInput))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.format(DateTimeFormatter.ofPattern(outputPattern))));现在使用forEach并以所需格式打印输出&nbsp; groupResult.forEach((k,v)->System.out.println("Date : "+ k+&nbsp; &nbsp; &nbsp; &nbsp; ", Age : " + v.stream().mapToInt(Person::getAge).sum()+&nbsp; &nbsp; &nbsp; &nbsp; ", UniqueCityCount : "+v.stream().map(Person::getCity).distinct().count()));最后输出Date : Mar-19, Age : 34, UniqueCityCount : 1Date : Jan-81, Age : 97, UniqueCityCount : 2您也可以使用YearMonth,但如果您需要自己的格式,它仍然是一回事&nbsp; String ym = YearMonth.parse(p1.getDateOfBirth(),&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DateTimeFormatter.ofPattern(patternInput))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .format(DateTimeFormatter.ofPattern(outputPattern));输出Mar-19按默认年月返回此格式ISO-8601 日历系统中的年月,例如 2007-12。

慕婉清6462132

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该组中的每个对象。计算年龄,求和。如果您想花哨一点,可以使用流来完成报告年龄和代码。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java