如果您不想添加任何新类,并且可以灵活地修改它们(实现接口),那么此解决方案将起作用。首先定义一个包含要比较的字段(getter)的接口:
interface ComparisionType {
String getFirstName();
String getLastName();
int getAge();
}
接下来,在您的 Student 和 Employee 类中实现它,如下所示:
@Builder
@Getter
@Setter
@ToString
class Student implements ComparisionType {
String firstName;
String lastName;
int age;
float gpa;
}
@Builder
@Getter
@Setter
@ToString
class Employee implements ComparisionType {
String firstName;
String lastName;
int age;
float salary;
}
以下是示例可执行代码(java-doc 说明每个方法的作用)。
public class StackOverflowTest {
public static void main(String[] args) {
List<ComparisionType> students = List.of(
Student.builder().firstName("firstName").lastName("lastName00").age(35).build(),
Student.builder().firstName("firstName1").lastName("lastName11").age(22).build(),
Student.builder().firstName("firstName2").lastName("lastName44").age(30).build());
List<ComparisionType> employees = List.of(
Employee.builder().firstName("firstName2").lastName("lastName11").age(12).build(),
Employee.builder().firstName("firstName3").lastName("lastName22").age(23).build(),
Employee.builder().firstName("firstName4").lastName("lastName33").age(35).build());
List<Student> commonStudents = getCommon(students, employees, Student.class, ComparisionType::getAge);
System.out.println(commonStudents);
List<Employee> commonEmployees = getCommon(students, employees, Employee.class, ComparisionType::getLastName);
System.out.println(commonEmployees);
}
/**
* Supply the 2 lists in first and second argument
* Third argument is which type of common objects you like as the output
* Fourth argument is which field do you want to compare to determine similar objects
*/
@SuppressWarnings("unchecked")
private static <T> List<T> getCommon(List<ComparisionType> students, List<ComparisionType> employees, Class<T> clazz,
Function<ComparisionType, Object> function) {
Map.Entry<List<ComparisionType>, List<ComparisionType>> comparingAndComparedTo = getComparingAndComparedTo(students, employees, clazz);
return (List<T>) comparingAndComparedTo.getKey().stream()
.filter(isMatch(comparingAndComparedTo.getValue(), function))
.collect(Collectors.toList());
}
/**
* Identifies the list to loop through
* to compare against the other list.
*/
private static <T> Map.Entry<List<ComparisionType>, List<ComparisionType>> getComparingAndComparedTo(List<ComparisionType> list1,
List<ComparisionType> list2, Class<T> clazz) {
return Optional.of(list1)
.filter(list -> list.get(0).getClass().equals(clazz)) // <-- Add better class check here
.map(list -> Map.entry(list1, list2))
.orElse(Map.entry(list2, list1));
}
/**
* Takes a list and checks if a field of an element
* matches the supplied field (from the function).
*/
private static Predicate<ComparisionType> isMatch(List<ComparisionType> list, Function<ComparisionType, Object> function) {
return type -> {
return list.stream()
.map(function)
.anyMatch(field -> field.equals(function.apply(type)));
};
}
}
getCommon 方法将为您提供所需类型的对象列表,并包含您要比较的字段,因此您可以灵活选择。
注意:我尚未测试此代码的性能。如果您设法计算出性能指标,请随时提及,我很想知道。
PS:我使用的是 Java11。