Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a scenario to sort the objects based on timestamp. The classes are as follows:

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
}

For an employee, there are 2 possibilities 1. it will have a list of address. 2. the list of address can be null

The address class has a field typeOfResidence which can have values such as Residence, Office, ForeignHome.

Each Employee can have list of address, one address will be Residential, other Office and so on. There can be multiple Residential addresses but only one Office address.

I want to sort the list of employees based on startDate of Address whose typeOfResidence=Office.

I have written the following code:

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();
}

Somehow this does not seem to be working. The employees are not sorted. Please help me to make it working.

like image 469
azaveri7 Avatar asked Apr 23 '18 07:04

azaveri7


People also ask

How do you sort a List of objects based on an attribute of the objects in Java 8?

Java 8 introduced a sort method in the List interface which can use a comparator. The Comparator. comparing() method accepts a method reference which serves as the basis of the comparison. So we pass User::getCreatedOn to sort by the createdOn field.

How do you sort an array of objects based on a property in Java?

To sort an Object by its property, you have to make the Object implement the Comparable interface and override the compareTo() method. Lets see the new Fruit class again. The new Fruit class implemented the Comparable interface, and overrided the compareTo() method to compare its quantity property in ascending order.

How to sort stream of objects by multiple fields in Java 8?

Java 8 example to sort stream of objects by multiple fields using comparators and Comparator.thenComparing () method. This method returns a lexicographic-order comparator with another comparator. It gives the same effect as SQL group by clause. 1. Create comparators for multiple fields

How to sort a list of objects by name in Java?

Here we are sorting a list of objects of Student class by name. Comparator sortingByName = new Comparator() { @Override public int compare(Student s1, Student s2) { return s1.getName().compareTo(s2.getName()); } }; Using Lambda expression: The Java 8 equivalent code using Lambda expression would look like this:

How to sort based on multiple fields in Java 8 comparator?

Java 8 Comparator Sorting - Multiple Fields Example using Collections.sort () To sort on a single field then need to use the Comparator.comparing () method from Comparator class. Sorting based on multiple fields, you first have to create the two comparators using Comparator.comparing () method and next call Comparator.thenComparing () method.

How do you sort a stream by multiple fields in SQL?

Create comparators for multiple fields To sort on multiple fields, we must first create comparator for each field on which we want to sort the stream. Then chain each comparator in desired order to give group by effect on complete sorting.


2 Answers

Your sortEmployeeListBasedOnStartDate method doesn't mutate the input List<Employee>. It creates a new sorted List<Address>, which you do nothing with.

If you want a sorted List<Employee>, you shouldn't be mapping the Employees to Addresses. You should produce a sorted List<Employee> and return that List.

Something like this should do:

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());
}

You might have to add some handling for the case where 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());
like image 95
Eran Avatar answered Oct 24 '22 05:10

Eran


If you want in-place sorting, you can use Collections.sort instead of streams.

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

Similarly, the null-filtering issue can be solved in-place as follows:

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

(btw, getLatestAddressByType should probably be an instance method of Employee)

like image 3
Marco Avatar answered Oct 24 '22 07:10

Marco