How to find Max Date in List<Object>?

JavaCollections

Java Problem Overview


Consider a class User

public class User{
  int userId;
  String name;
  Date date;
}

Now I have a List<User> of size 20, how can I find the max date in the list without using manual iterator?

Java Solutions


Solution 1 - Java

Since you are asking for lambdas, you can use the following syntax with Java 8:

Date maxDate = list.stream().map(u -> u.date).max(Date::compareTo).get();

or, if you have a getter for the date:

Date maxDate = list.stream().map(User::getDate).max(Date::compareTo).get();

Solution 2 - Java

A small improvement from the accepted answer is to do the null check and also get full object.

public class DateComparator {

public static void main(String[] args) throws ParseException {
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

	List<Employee> employees = new ArrayList<>();
	employees.add(new Employee(1, "name1", addDays(new Date(), 1)));
	employees.add(new Employee(2, "name2", addDays(new Date(), 3)));
	employees.add(new Employee(3, "name3", addDays(new Date(), 6)));
	employees.add(new Employee(4, "name4", null));
	employees.add(new Employee(5, "name5", addDays(new Date(), 4)));
	employees.add(new Employee(6, "name6", addDays(new Date(), 5)));
	System.out.println(employees);
	Date maxDate = employees.stream().filter(emp -> emp.getJoiningDate() != null).map(Employee::getJoiningDate).max(Date::compareTo).get();
	System.out.println(format.format(maxDate));
	//Comparator<Employee> comparator = (p1, p2) -> p1.getJoiningDate().compareTo(p2.getJoiningDate());
	Comparator<Employee> comparator = Comparator.comparing(Employee::getJoiningDate);
	Employee maxDatedEmploye = employees.stream().filter(emp -> emp.getJoiningDate() != null).max(comparator).get();
	System.out.println(" maxDatedEmploye : " + maxDatedEmploye);
	
	Employee minDatedEmployee = employees.stream().filter(emp -> emp.getJoiningDate() != null).min(comparator).get();
	System.out.println(" minDatedEmployee : " + minDatedEmployee);
	
}

public static Date addDays(Date date, int days) {
	Calendar cal = Calendar.getInstance();
	cal.setTime(date);
	cal.add(Calendar.DATE, days); // minus number would decrement the days
	return cal.getTime();
}
}

You would get below results :

 [Employee [empId=1, empName=name1, joiningDate=Wed Mar 21 13:33:09 EDT 2018],
Employee [empId=2, empName=name2, joiningDate=Fri Mar 23 13:33:09 EDT 2018],
Employee [empId=3, empName=name3, joiningDate=Mon Mar 26 13:33:09 EDT 2018],
Employee [empId=4, empName=name4, joiningDate=null],
Employee [empId=5, empName=name5, joiningDate=Sat Mar 24 13:33:09 EDT 2018],
Employee [empId=6, empName=name6, joiningDate=Sun Mar 25 13:33:09 EDT 2018]
]
2018-03-26
 maxDatedEmploye : Employee [empId=3, empName=name3, joiningDate=Mon Mar 26 13:33:09 EDT 2018]

 minDatedEmployee : Employee [empId=1, empName=name1, joiningDate=Wed Mar 21 13:33:09 EDT 2018]

Update : What if list itself is empty ?

		Date maxDate = employees.stream().filter(emp -> emp.getJoiningDate() != null).map(Employee::getJoiningDate).max(Date::compareTo).orElse(new Date());
	System.out.println(format.format(maxDate));
	Comparator<Employee> comparator = Comparator.comparing(Employee::getJoiningDate);
	Employee maxDatedEmploye = employees.stream().filter(emp -> emp.getJoiningDate() != null).max(comparator).orElse(null);
	System.out.println(" maxDatedEmploye : " + maxDatedEmploye);

Solution 3 - Java

Comparator<User> cmp = new Comparator<User>() {
    @Override
    public int compare(User user1, User user2) {
        return user1.date.compareTo(user2.date);
    }
};

Collections.max(list, cmp);

Solution 4 - Java

LocalDate maxDate = dates.stream()
                            .max( Comparator.comparing( LocalDate::toEpochDay ) )
                            .get();
 
LocalDate minDate = dates.stream()
                            .min( Comparator.comparing( LocalDate::toEpochDay ) )
                            .get();

Solution 5 - Java

Just use Kotlin!

val list = listOf(user1, user2, user3)
val maxDate = list.maxBy { it.date }?.date

Solution 6 - Java

troubleshooting-friendly style

You should not call .get() directly. Optional<>, that Stream::max returns, was designed to benefit from .orElse... inline handling.

> If you are sure your arguments have their size of 2+:

list.stream()
    .map(u -> u.date)
    .max(Date::compareTo)
    .orElseThrow(() -> new IllegalArgumentException("Expected 'list' to be of size: >= 2. Was: 0"));

> If you support empty lists, then return some default value, for example:

list.stream()
    .map(u -> u.date)
    .max(Date::compareTo)
    .orElse(new Date(Long.MIN_VALUE));

CREDITS to: @JimmyGeers, @assylias from the accepted answer.

Solution 7 - Java

self-explanatory style

import static java.util.Comparator.naturalOrder;
...

    list.stream()
        .map(User::getDate)
        .max(naturalOrder())
        .orElse(null)          // replace with .orElseThrow() is the list cannot be empty

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2783484View Question on Stackoverflow
Solution 1 - JavaassyliasView Answer on Stackoverflow
Solution 2 - JavaJajikanth pydimarlaView Answer on Stackoverflow
Solution 3 - Javagiannis christofakisView Answer on Stackoverflow
Solution 4 - JavaMike MoreiraView Answer on Stackoverflow
Solution 5 - JavaKirill GroshkovView Answer on Stackoverflow
Solution 6 - JavaepoxView Answer on Stackoverflow
Solution 7 - JavaepoxView Answer on Stackoverflow