java 8 个流,用于根据特定字段对对象列表进行排序

java 8 stream for sorting a list of objects based on particular field

我有一个场景可以根据时间戳对对象进行排序。 class如下:

class Employee 
{
    private String name;
    private List<Address> addresses;

    //...
    //Getters and setters for all fields
}

public class Address
{
    private String city;
    private Timestamp startDate;
    private Timestamp endDate;
    private String typeOfResidence;

    //...
    //Getters and setters for all the fields
}

对于一个员工,有两种可能 1. 它将有一个地址列表。 2.地址列表可以为空

地址 class 有一个字段 typeOfResidence,它可以包含 Residence、Office、ForeignHome 等值。

每个Employee可以有地址列表,一个地址是住宅,另一个是办公室等等。住宅地址可以有多个,办公地址只能有一个。

我想根据 typeOfResidence=Office 的地址的开始日期对员工列表进行排序。

我写了下面的代码:

private void sortEmployeeListBasedOnStartDate(List<Employee> employeeList)
{
    Comparator<Address> byTimeStamp = Comparator.comparing(
        Address::getStarteDate,
        (ts1, ts2) -> ts1.toGregorianCalendar().compareTo(ts2.toGregorianCalendar())
    );

    employeeList.stream()
        .map(x -> getLatestAddressByType(x, "Office"))
        .filter(y -> y!=null)
        .sorted(byTimeStamp.reversed())
        .collect(Collectors.toList());
}

public Address getLatestAddressByType(Employee employee, String type)
{
    if(role != null && brokerageManagedProposalType != null)
    {
         return getUserAddress(employee).stream()
            .filter(address-> address.getTypeOfResidence().equals(type))
            .findFirst()
            .orElse(null);
    }
    return null;
}

public List<Address> getUserAddress(Employee employee)
{
    if (!NullChecker.isNull(employee) && !NullChecker.isNull(employee.getAddress()))
    {
        return employee.getAddress();
    }
    return Collections.emptyList();
}

这似乎不起作用。员工没有分类。请帮我让它工作。

您的 sortEmployeeListBasedOnStartDate 方法不会改变输入 List<Employee>。它会创建一个新的排序 List<Address>,您无需对其进行任何操作。

如果您想要排序的 List<Employee>,则不应将 Employee 映射到 Address。您应该生成 List<Employee> 和 return 的 List.

应该这样做:

private List<Employee> sortEmployeeListBasedOnStartDate(List<Employee> employeeList)
{
    Comparator<Address> byTimeStamp = Comparator.comparing(
        Address::getStarteDate,
        (ts1, ts2) -> ts1.toGregorianCalendar().compareTo(ts2.toGregorianCalendar())
    );

    return employeeList
        .stream()
        .sorted((e1,e2)->byTimeStamp.compare(getLatestAddressByType(e2, "Office"),getLatestAddressByType(e1, "Office")))
        .collect(Collectors.toList());
}

您可能需要为 getLatestAddressByType() returns null:

的情况添加一些处理
    return employeeList
        .stream()
        .filter(e->getLatestAddressByType(e, "Office") != null)
        .sorted((e1,e2)->byTimeStamp.compare(getLatestAddressByType(e2, "Office"),getLatestAddressByType(e1, "Office")))
        .collect(Collectors.toList());

您的问题在这里:

employeeList.stream()
    .map(x -> getLatestAddressByType(x, "Office"))
    .filter(y -> y!=null)
    .sorted(byTimeStamp.reversed())
    .collect(Collectors.toList());

这不是就地排序。 employeeList 中的值保持完全相同。 collect 正在创建一个新的 List 实例,该实例从未分配给变量或返回 - 该实例只是简单地创建,然后立即无法辨认以进行垃圾回收。

如果要就地排序,可以使用 Collections.sort 而不是流。

Collections.sort(employeeList, 
    (e1,e2) -> byTimeStamp.compare(
        getLatestAddressByType(e2, "Office"),
        getLatestAddressByType(e1, "Office") );

同样,null-过滤问题可以按如下方式就地解决:

employeeList.removeIf(e -> getLatestAddressByType(e, "Office") == null);

(顺便说一句,getLatestAddressByType 应该是 Employee 的一个实例方法)