Nice to meet you, my name is @ekuro and I am making a labor management service called Gozal. At Gozal, we are doing domain-driven development to better incorporate labor management into software. We are constantly searching for better and more versatile classes so that we can easily respond to changes in business processes due to work style reforms.
This time, I thought about "what to use" and "where to define" to sort the list of employees by employee number.
Consider the process of sorting the list of employees List <Employee> employees;
by employee number.
Employee.java
@Getter
@AllArgsConstructor
public class Employee {
//employee number
private EmployeeNumber number;
//Personal information such as name and date of birth
private Personal personal;
}
@Getter
@AllArgsConstructor
public class EmployeeNumber {
private String number;
}
Typical methods for sorting objects in Java 8 are Collections.sort and the Sorted method of the Stream API.
When using Collections, you will need to use one of the following two sort methods.
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
Also, when using the Stream API, two types of methods are also provided.
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
In either case, when using the first method, the class to be sorted must implement Comparable, and when using the second method, the functional interface Comparator
Both Comparable and Comparator are classes that define magnitude comparisons, but let's first look at the differences.
Comparable is an interface where only public int compareTo (To);
is defined.
By making the object you want to compare inherit Comparable and implementing compareTo, you can define how to compare that object. The compareTo method compares the argument with itself.
On the other hand, the Comparator interface defines a method that has two arguments, ʻint compare (To1, To2); `. Since you can implement multiple Comparator for the objects you want to compare, it is useful when you want to define sorting by various keys.
Consider the case of the Employee class. The Employee class has personal information such as name in addition to the employee number. Therefore, it is possible to sort by various information in the future. Therefore, it seems better to create a Comparator for each item to be compared instead of inheriting Comparator in the Employee class.
Let's write a method that actually returns a Comparator to sort the employee list by employee number. [^ 1]
Employee.java
@Getter
@AllArgsConstructor
public class Employee {
//employee number
private EmployeeNumber number;
//Personal information such as name and date of birth
private Personal personal;
public static Comparator<Employee> orderByNumber() {
return Comparator.comparing(
//Simple employee number string comparison
(Employee employee) -> employee.getNumber().getNumber());
}
}
When actually sorting,
List<Employee> employees = ~;
Collections.sort(employees, Employee.orderByNumber());
Can be written.
In the above example, the comparison method ʻorderByNumber ()` is defined in the Employee class. However, by nature, comparing employee numbers is a property that employee number classes should have. So move the comparison method to the EmployeeNumber class.
Employee.java
@Getter
@AllArgsConstructor
public class Employee {
//employee number
private EmployeeNumber number;
//Personal information such as name and date of birth
private Personal personal;
public static Comparator<Employee> orderByNumber() {
//Using EmployeeNumber as the key for comparison, the sorting process is left to the order method of EmployeeNumber.
return Comparator.comparing(Employee::getNumber, EmployeeNumber.order());
}
}
EmployeeNumber.java
@Getter
@AllArgsConstructor
public class EmployeeNumber {
private String number;
public static Comparator<EmployeeNumber> order() {
return Comparator.comparing(EmployeeNumber::getNumber);
}
}
The comparison method was completed with EmployeeNumber, making it a more versatile class. This time, the size comparison process of EmployeeNumber is a simple logic, but if numbers and character strings are mixed, it will be a little complicated process. In that case, it will be better to see if the comparison process is defined in EmployeeNumber.
Since multiple Comparators can be defined for one object, it is easy to use them a lot. So check if you have used Comparator where you should inherit Comparable.
It seems that the sorting of Employee Number this time will not be sorted by anything other than number in the future. Therefore, it is better to use Comparable for Employee Number comparison processing.
Employee.java
@Getter
@AllArgsConstructor
public class Employee {
//employee number
private EmployeeNumber number;
//Personal information such as name and date of birth
private Personal personal;
public static Comparator<Employee> orderByNumber() {
//EmployeeNumber implements Comparable, which reduces the number of arguments.
return Comparator.comparing(Employee::getNumber);
}
}
EmployeeNumber.java
@Getter
@AllArgsConstructor
public class EmployeeNumber implements Comparable<EmployeeNumber> {
private String number;
@Override
public int compareTo(@Nonnull EmployeeNumber other) {
return this.number.compareTo(other.number);
}
}
By inheriting Comparable from EmployeeNumber, unnecessary description is eliminated and the processing content is refined.
By writing the appropriate processing in the appropriate place in this way, it will be possible to smoothly respond to requests such as "I want to sort by name" and "I want to sort by birthday" in the future.
We believe that better understanding of concepts and designing classes will not only make it easier to implement and provide easy-to-understand source code, but will also lead to the discovery of more sophisticated new business flows.
At Gozal, we will stick to how to grasp the concept in order to create a new work experience that will make the world stunning by sending engineers.
Recruiting engineers from the world of labor management to eliminate unnecessary manual work! Recruiting front engineers to create a moving labor management SaaS!
[^ 1]: The static comparing method provided in the Comparator interface takes Function as an argument and compares the result of Function with compareTo when there is only one argument.
Recommended Posts