Never use strings to represent date-time information. Instead, use Java 8 classes from java.time
package like LocalDateTime
.
Assuming that Employee
is reimplemented like that:
public class Employee {
private String name;
private LocalDateTime date;
// constructor, getters, etc.
}
The comparator would be:
Comparator<Employee> byDate = Comparator.comparing(Employee::getDate);
It happens to be the same as you've written, and since your original question was how to create a comparator based on more than one attribute, here is another example:
public static final Comparator<Employee> BY_NAME_DATE =
Comparator.comparing(Employee::getName)
.thenComparing(Employee::getDate);
You can declare comparators for a class that has no natural order right inside this class as public static
field and use whenever you need them, instead of creating a new comparator on the spot each time.
With Java 8 a lot of handy static methods were introduced in the Comparator
interface. You can chain these methods in a fluent way because they all give you a new comparator. To combine two comparators, you can use methods like thenComparing()
and thenComparingInt()
. To learn how to build comparators using Java-8 methods, have a look at this tutorial.
Note that there could be some intricate cases related to how the type inference works in Java, so I'm also suggesting reading this question.
I'm not sure if duplicates dates can be a problem
There would be no problem with employees having identical latest date-time information associated with them, since you want to get the first encountered element. The problem can occur if there's no data in the stream at all.
That leads to the second suggestion - avoid invoking get()
on the optional object, unless you didn't check the presence of the result (which in many cases is inconvenient and if you're finding yourself performing this check that might indicate that you're not leveraging Optional
API to its full power).
If you have a look at the documentation of Java 10 and above, you'll see the following API note in the description of get()
:
The preferred alternative to this method is orElseThrow()
.
Method get()
will produce NoSuchElementException
in case of the empty optional, if you're OK with such outcome then apply orElseThrow()
instead, it acts in the same way and makes your intention obvious to the reader of the code.
This method also has an overloaded version which allows you to specify the type of exception to throw.
Employee emp = getEmployeeList().stream()
.max(byDate)
.orElseThrow();
You're not limited to using the methods mentioned above, Optional
offers you other possibilities, for instance, you can provide a default value using orElse()
.