java - 如何改进 2 个对象字段的繁琐比较

标签 java reflection

我们有一个程序通过检查 Student 的每个字段并计算差异来比较数千对 Students:

class Student{

   String name;
   String address;
   String biologyCourse;
    .....
   // about 100 other fields
}

和计数器 POJO 类:

class Counters{
  long bothStudentsHaveName;
  long onlyLeftHasName;
  long onlyRightHasName;

   ......
  // number of fields in Student * 3 (both, only left, only right)
}

我们的比较函数接受 2 个学生加上计数器对象,需要扫描字段并更新相关计数器:

    public void compareStudents(Student left, Student right, Counters counters){

        if (!StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name) ){
            counters.bothStudentsHaveName++;
        } else if (StringUtils.isEmpty(left.name) && !StringUtils.isEmpty(right.name)){
            counters.onlyRightHasName++;
        } else if (!StringUtils.isEmpty(left.name) && StringUtils.isEmpty(right.name))){
            counters.onlyLeftHasName++;
        }

     /// and now??
}

此时,我们可以像上面那样添加 100 个以上的 if/else 三元组 - 但我们相信应该有更简单的方法来做到这一点。

Reflection 可以是一个选项,也可以是 X 维数组,但我们能否以某种方式编写代码,使比较和计数更加通用?

最佳答案

我已经用一个循环解决了你的问题。但在这里我假设所有字段的命名约定都与您的问题中描述的相同。在这里,我动态访问 Student 字段并相应地更新 Counter 字段。这是完整的解决方案:

解决方案类:

public class Solution {
    public void compareStudents(Student left, Student right, Counter counter) throws Exception {
        for (Field field : Student.class.getDeclaredFields()) {
            Object leftValue = field.get(left);
            Object rightValue = field.get(right);

            String fieldName = field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1);

            if(leftValue != null && rightValue != null) {
                Field counterField = Counter.class.getDeclaredField("bothStudentsHave" + fieldName);
                counterField.set(counter, (long) counterField.get(counter) + 1);
            } else if (leftValue != null) {
                Field counterField = Counter.class.getDeclaredField("onlyLeftHas" + fieldName);
                counterField.set(counter, (long) counterField.get(counter) + 1);
            } else if (rightValue != null) {
                Field counterField = Counter.class.getDeclaredField("onlyRightHas" + fieldName);
                counterField.set(counter, (long) counterField.get(counter) + 1);
            }
        }
    }
}

学生类(class):

class Student {
    String name;
    String address;
    String biologyCourse;
}

计数器类:

class Counter {
    // name
    long bothStudentsHaveName;
    long onlyLeftHasName;
    long onlyRightHasName;
    // address
    long bothStudentsHaveAddress;
    long onlyLeftHasAddress;
    long onlyRightHasAddress;
    // biologyCourse
    long bothStudentsHaveBiologyCourse;
    long onlyLeftHasBiologyCourse;
    long onlyRightHasBiologyCourse;
    // ... and so on


    @Override
    public String toString() {
        return "Counter{" + "\n" +
                "\tbothStudentsHaveName = " + bothStudentsHaveName + "\n" +
                "\t, onlyLeftHasName = " + onlyLeftHasName + "\n" +
                "\t, onlyRightHasName = " + onlyRightHasName + "\n" +
                "\t, bothStudentsHaveAddress = " + bothStudentsHaveAddress + "\n" +
                "\t, onlyLeftHasAddress = " + onlyLeftHasAddress + "\n" +
                "\t, onlyRightHasAddress = " + onlyRightHasAddress + "\n" +
                "\t, bothStudentsHaveBiologyCourse = " + bothStudentsHaveBiologyCourse + "\n" +
                "\t, onlyLeftHasBiologyCourse = " + onlyLeftHasBiologyCourse + "\n" +
                "\t, onlyRightHasBiologyCourse = " + onlyRightHasBiologyCourse + "\n" +
                '}';
    }
}

测试类:

public class Tester {
    public static void main(String[] args) throws Exception {
        // Creating Dummy Variables
        Student student1 = new Student();
        student1.name = "Test";
        student1.biologyCourse = "Yes";
        Student student2 = new Student();
        student2.name = "Test1";
        student2.address = "abc street";
        Counter counter = new Counter();

        // Comparing Students
        Solution solution = new Solution();
        solution.compareStudents(student1, student2, counter);

        // Printing Counter
        System.out.println(counter);
    }
}

Output:

Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}

关于java - 如何改进 2 个对象字段的繁琐比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57782515/

相关文章:

java - 将 JPanel 类传递给 JAVA 中的主类

java - 如何表示反斜杠

java - 如何使用 Ant(在 Eclipse 之外......)构建一个 Selenium Web Driver java 应用程序?

c# - 循环中的高效反射

java - 为什么这个类不能序列化?

java - org.codehaus.cargo.container.ContainerException : Cannot create deployable

java - Tomcat 8 无法通过反射访问 protected 成员

actionscript-3 - Flash AS3 - 添加反射/镜像到可拖动的动画片段

c# - 为什么我不能使用反射加载 AssemblyVersion 属性?

c# - 使用反射覆盖 DLL 中的方法