![](/img/trans.png)
[英]how to calculate the exact age of a person from date of birth in android
[英]Get youngest Person from List<Person> where Person has date of Birth in string ISO8601 fromat
class Person {
String name;
String id;
String dateOfBirth;
int salary;
}
List <Person> listOfPersons; // Consider that list is filled with some data
例如dateOfBirth = "2018-12-10T13:49:51.141Z";
出生日期在 ISO8601 中,可以使用Date.from(Instant.parse(dateOfBirth));
转换为java.util.Date
; 如果这可以帮助对列表进行排序。
那么有没有办法在 JAVA 8 中使用流或不错的解决方案来从人员列表中获取最年轻的人员?
附加说明:无法更改 Person 类。
你可以这样做
Person youngestPerson = listOfPersons.stream()
.reduce((p1, p2) -> LocalDateTime.parse(p1.getStringDateofBirth()).isAfter(LocalDateTime.parse(p2.getStringDateofBirth()))?p1:p2)
.orElse(null)
UTC ISO-8601 日期字符串可以按字典顺序进行比较。 因此,我认为最优雅的 Java 8 解决方案是:
Person youngest = listOfPersons.stream()
.max(Comparator.comparing(p -> p.dateOfBirth)).get();
如果您不信任字符串比较,或者您的时区无处不在,您可以根据需要解析日期:
Person youngest = listOfPersons.stream()
.max(Comparator.comparing(p -> LocalDateTime.parse(p.dateOfBirth, DateTimeFormatter.ISO_DATE_TIME)))
.get();
甚至:
Person youngest = listOfPersons.stream()
.max(Comparator.comparing(p -> Instant.parse(p.dateOfBirth))).get();
请注意,您可能应该使用LocalDateTime
(或Instant
)而不是Date
,因为 Java 8 已经远离了旧的日期/时间 API(这里有一个很好的概述)。 如果您使用LocalDateTime
,则需要使用ISO_DATE_TIME
格式化程序在最后处理Z
区域。
感兴趣的 API:
Stream
是 Java 8 的一种……可迭代的转换接口,支持许多方便的方法和方法链。 所有Collection
对象都有一个stream()
成员来获取一个。Stream.max()
根据您指定的某个Comparator
返回流中的最大值(可以是 lambda 函数,或者在上述情况下,只是一个Comparator
对象)。
Optional<Person>
(例如,如果列表为空,则可能没有值),因此get()
获取该值,或者您可以将其保留为Optional
如果您愿意,或者您如果您希望空列表为空,可以使用例如orElse(null)
而不是get()
。Comparator.comparing()
是一个方便的小实用程序,它构造一个Comparator<T>
给定一个将T
映射到可比较值的函数。所以在上面的代码中:
p -> p.dateOfBirth
(或p -> LocalDateTime.parse(p.dateOfBirth)
,你的电话)是一个 lambda 函数,它将一个人映射到他们的生日。Comparator.comparing(...)
,当给定所述键映射函数时,返回一个Comparator
两个人的出生日期的 Comparator,根据您使用的是String
还是LocalDateTime
版本执行适当的比较。max()
返回具有最大日期的对象,即最年轻的人。get()
只是将Person
从Optional<Person>
中取出。完整示例(链接到上面的 ideone):
import java.util.*;
import java.lang.*;
import java.io.*;
import java.time.*;
import java.time.format.*;
class Ideone {
public static void main (String[] args) throws java.lang.Exception {
Person youngest;
// you could do string comparison if you know the timezones are consistent:
youngest = listOfPersons.stream()
.max(Comparator.comparing(p -> p.dateOfBirth)).get();
System.out.println("youngest is: " + youngest.name + " " + youngest.dateOfBirth);
// or you could just parse the date, a safer option:
youngest = listOfPersons.stream()
.max(Comparator.comparing(p -> LocalDateTime.parse(p.dateOfBirth, DateTimeFormatter.ISO_DATE_TIME))).get();
System.out.println("youngest is: " + youngest.name + " " + youngest.dateOfBirth);
}
//------------------------------------
// types from OP:
static class Person{
String name;
String id;
String dateOfBirth;
int salary;
}
static List <Person> listOfPersons;
//------------------------------------
// boring example data initialization:
// make an iso birthdate string given an age (for initializing data)
static String fromAge (int years) {
//return LocalDateTime.now().minusYears(years).toString();
// add zone to emulate OP's input:
return LocalDateTime.now().minusYears(years).toString() + 'Z';
}
// make up some data
static {
listOfPersons = List.of(
// fine for example, but i wouldn't init like this in production
new Person() {{ name="helga"; dateOfBirth=fromAge(22); }},
new Person() {{ name="mortimer"; dateOfBirth=fromAge(48); }},
new Person() {{ name="gertrude"; dateOfBirth=fromAge(6); }},
new Person() {{ name="jebediah"; dateOfBirth=fromAge(39); }}
);
listOfPersons.forEach(p -> System.out.println(p.name + ' ' + p.dateOfBirth));
}
}
输出:
helga 2000-06-23T03:07:26.084850Z
mortimer 1974-06-23T03:07:26.126628Z
gertrude 2016-06-23T03:07:26.126894Z
jebediah 1983-06-23T03:07:26.127948Z
youngest is: gertrude 2016-06-23T03:07:26.126894Z
youngest is: gertrude 2016-06-23T03:07:26.126894Z
正如其他人所建议的那样,使用LocalDateTime
。 LocalDateTime
具有非常方便的功能,完全适合您的问题。 您可以直接将您的字符串解析到其中,只需从您的 ISO 字符串中删除“Z”就可以了:
LocalDateTime someBirthday = LocalDateTime.parse("2018-12-10T13:49:51.141");
下一步,编写一个比较器:
public class BirthdayComparator implements Comparator<LocalDateTime> {
@Override
public int compare(LocalDateTime date1, LocalDateTime date2) {
if(date1.isAfter(date2)) {
return 1;
} else if (date1.equals(date2)) {
return 0;
} else {
return -1;
}
}
}
而已。 您现在可以按出生日期排序。
更新
最后一句警告:此代码忽略时区。 准确地说,它隐含地假设,所有给定的生日都在同一个时区。 如果您必须与全球各地的人打交道,这可能会出现问题......
这是一种方法。
record Person(String name, String id, String dateOfBirth,
int salary) {}
List<Person> list = new ArrayList<>(List.of(
new Person("Jim", "10", "2018-12-10T13:49:51.141Z",
20),
new Person("Mary", "11", "2018-12-15T13:49:51.141Z",
20),
new Person("Bob", "12", "2018-12-12T13:49:51.141Z",
20)));
maxBy
,因为最年轻的人会在离时代更远的地方出生。Instant
。 您无法使用LocalDateTime
解析给定的格式示例Person youngest = list.stream().collect(Collectors.maxBy(Comparator
.comparing(p -> Instant.parse(p.dateOfBirth)))).get();
System.out.println(youngest);
印刷
Person[name=Mary, id=11, dateOfBirth=2018-12-15T13:49:51.141Z, salary=20]
请注意, maxBy
返回一个Optional
,因此最后调用get()
。 您可能希望返回Optional<Person>
然后根据查找的成功提取日期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.