从 List<Person> 中获取最年轻的 Person,其中 Person 的出生日期位于字符串 ISO8601 fromat 中

Van*_*vic 1 java datetime java-stream

class Person {
    String name;
    String id;
    String dateOfBirth;
    int salary;
 }

 List <Person> listOfPersons; // Consider that list is filled with some data
Run Code Online (Sandbox Code Playgroud)

例如dateOfBirth = "2018-12-10T13:49:51.141Z";

出生日期采用 ISO8601 格式, 如果可以帮助对列表进行排序,则可以将其转换为java.util.Date with 。Date.from(Instant.parse(dateOfBirth));

那么,有什么方法可以使用 JAVA 8 中的流或不错的解决方案来从人员列表中获取最年轻的人员吗?

附加注释:Person 类不能更改。

小智 5

你可以这样做

Person youngestPerson = listOfPersons.stream()
.reduce((p1, p2) -> LocalDateTime.parse(p1.getStringDateofBirth()).isAfter(LocalDateTime.parse(p2.getStringDateofBirth()))?p1:p2)
.orElse(null)
Run Code Online (Sandbox Code Playgroud)


Jas*_*n C 5

UTC ISO-8601 日期字符串可以按字典顺序进行比较。因此,我认为最优雅的 Java 8 解决方案是:

Person youngest = listOfPersons.stream()
    .max(Comparator.comparing(p -> p.dateOfBirth)).get();
Run Code Online (Sandbox Code Playgroud)

如果您不信任字符串比较,或者您的时区到处都是,您可以根据需要解析日期:

Person youngest = listOfPersons.stream()
    .max(Comparator.comparing(p -> LocalDateTime.parse(p.dateOfBirth, DateTimeFormatter.ISO_DATE_TIME)))
    .get();
Run Code Online (Sandbox Code Playgroud)

甚至

Person youngest = listOfPersons.stream()
    .max(Comparator.comparing(p -> Instant.parse(p.dateOfBirth))).get();
Run Code Online (Sandbox Code Playgroud)

请注意,您可能应该使用LocalDateTime(或Instant) 而不是Date,因为 Java 8 已经放弃了旧的日期/时间 API(这里有一个很好的概述)。如果您使用的是,则需要使用ISO_DATE_TIME格式化程序来处理Z末尾的区域LocalDateTime

可运行的示例在这里。


感兴趣的API:

  • Stream是 Java 8 的...可迭代转换接口,支持许多方便的方法和方法链接。所有Collection对象都有stream()一个用于获取对象的成员。
  • Stream.max()根据您指定的值返回流中的最大值Comparator(可以是 lambda 函数,或者如上例所示,只是一个Comparator对象)。
    • 在这种情况下,返回值实际上是 an Optional<Person>(例如,如果列表为空,则可能没有值),因此get()获取该值,或者如果您愿意,您可以将其保留为 an Optional,或者您可以使用 egorElse(null)代替get()if you' d 宁愿它是 null 对于空列表。
  • Comparator.comparing()是一个方便的小实用程序,它构造Comparator<T>给定的函数,将 a 映射T到可比较的值。

所以在上面的代码中:

  • p -> p.dateOfBirth(或者p -> LocalDateTime.parse(p.dateOfBirth),您的调用)是一个 lambda 函数,它将一个人映射到他们的出生日期。
  • Comparator.comparing(...),当给定所述键映射函数时,返回一个Comparator比较两个人的出生日期的值,根据您是否使用StringLocalDateTime版本执行适当的比较。
  • 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));
    }

    
} 
Run Code Online (Sandbox Code Playgroud)

输出:

Person youngest = listOfPersons.stream()
    .max(Comparator.comparing(p -> p.dateOfBirth)).get();
Run Code Online (Sandbox Code Playgroud)