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 中,
如果可以幫助對串列進行排序,可以將其轉換為java.util.Date
with 。Date.from(Instant.parse(dateOfBirth));
那么有沒有辦法在 JAVA 8 中使用流或不錯的解決方案來從人員串列中獲取最年輕的人員?
附加說明:無法更改 Person 類。
uj5u.com熱心網友回復:
你可以這樣做
Person youngestPerson = listOfPersons.stream()
.reduce((p1, p2) -> LocalDateTime.parse(p1.getStringDateofBirth()).isAfter(LocalDateTime.parse(p2.getStringDateofBirth()))?p1:p2)
.orElse(null)
uj5u.com熱心網友回復:
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
(or Instant
) 而不是Date
,因為 Java 8 已經遠離舊的日期/時間 API(這里有一個很好的概述)。如果您ISO_DATE_TIME
使用.Z
LocalDateTime
可運行的示例在這里。
感興趣的 API:
Stream
是 Java 8 的一種……可迭代的轉換介面,支持許多方便的方法和方法鏈。所有Collection
物件都有一個stream()
用于獲取的成員。Stream.max()
根據您指定的一些值回傳流中的最大值Comparator
(可以是 lambda 函式,或者在上述情況下,只是一個Comparator
物件)。- 在這種情況下,回傳值實際上是一個(例如,如果串列為空,則
Optional<Person>
可能沒有值),因此獲取該值,或者您get()
可以將其保留為d寧愿它為空串列為空。Optional
orElse(null)
get()
- 在這種情況下,回傳值實際上是一個(例如,如果串列為空,則
Comparator.comparing()
是一個方便的小實用程式,它構造一個Comparator<T>
給定的函式,將 a 映射T
到一個可比較的值。
所以在上面的代碼中:
p -> p.dateOfBirth
(或者p -> LocalDateTime.parse(p.dateOfBirth)
,你的電話)是一個 lambda 函式,它將一個人映射到他們的生日。Comparator.comparing(...)
,當給定所述鍵映射函式時,回傳 aComparator
比較兩個人的出生日期,根據您使用的是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
uj5u.com熱心網友回復:
根據其他人的建議,使用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;
}
}
}
而已。您現在可以按出生日期排序。
更新
最后一句警告:此代碼忽略時區。準確地說,它隱含地假設,所有給定的生日都在同一個時區。如果您必須與全球各地的人打交道,這可能會出現問題......
uj5u.com熱心網友回復:
這是一種方法。
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>
,然后根據查找的成功提取日期。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/496329.html
上一篇:按日期過濾DataFrame