Java 如何改进两个对象的繁琐比较';领域

Java 如何改进两个对象的繁琐比较';领域,java,reflection,Java,Reflection,我们有一个程序,通过检查学生的每个字段并计算差异来比较数千对学生: class Student{ String name; String address; String biologyCourse; ..... // about 100 other fields } 和计数器POJO类: class Counters{ long bothStudentsHaveName; long onlyLeftHasName; long onlyRightHa

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

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个学生和counters对象,需要扫描字段并更新相关计数器:

    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
三元组,但我们相信应该有一种更简单的方法来做到这一点


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

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

解决方案类别:

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 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);
    }
}
Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}
学生班:

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 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);
    }
}
Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}
计数器类:

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 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);
    }
}
Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}
测试仪类别:

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 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);
    }
}
Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}
输出:

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 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);
    }
}
Counter{
  bothStudentsHaveName = 1
  , onlyLeftHasName = 0
  , onlyRightHasName = 0
  , bothStudentsHaveAddress = 0
  , onlyLeftHasAddress = 0
  , onlyRightHasAddress = 1
  , bothStudentsHaveBiologyCourse = 0
  , onlyLeftHasBiologyCourse = 1
  , onlyRightHasBiologyCourse = 0
}

如果你不断地修改相同的基本字段模式,那么考虑把它提取到一个类中。例如,引入一个

FieldComparison
类,它看起来有点像这样:

public class FieldComparisonCounter {
  public int bothHave;
  public int onlyLeftHas;
  public int onlyRightHas;

  // constructor, getters, setters left as an exercise for the reader
}
public void compareField(String fieldName, String leftValue, String rightValue) {
  FieldComparisonCounter counter = counters.get(fieldName);
  if (counter == null) {
    counter = new FieldComparisonCounter();
    counters.put(fieldName, counter);
  }
  boolean leftHas = !StringUtils.isEmpty(leftValue);
  boolean rightHas = !StringUtils.isEmpty(rightValue);
  if (leftHas && rightHas) {
    counter.bothHave++;
  } else if (leftHas) {
    counter.onlyLeftHas++;
  } else if (rightHas) {
    counter.onlyRightHas++;
  }
}
然后在某个地方有一个
映射计数器
,方法如下:

public class FieldComparisonCounter {
  public int bothHave;
  public int onlyLeftHas;
  public int onlyRightHas;

  // constructor, getters, setters left as an exercise for the reader
}
public void compareField(String fieldName, String leftValue, String rightValue) {
  FieldComparisonCounter counter = counters.get(fieldName);
  if (counter == null) {
    counter = new FieldComparisonCounter();
    counters.put(fieldName, counter);
  }
  boolean leftHas = !StringUtils.isEmpty(leftValue);
  boolean rightHas = !StringUtils.isEmpty(rightValue);
  if (leftHas && rightHas) {
    counter.bothHave++;
  } else if (leftHas) {
    counter.onlyLeftHas++;
  } else if (rightHas) {
    counter.onlyRightHas++;
  }
}
然后添加一个新的字段比较就像调用

compareField("name", left.name, right.name);

这样做的目的是什么?我的意思是,你为什么要计算每个字段之间的差异?@MushifAliNawaz因为这是业务需要为什么这些计数器
很长
?如果它们只能递增一次?在我看来,
boolean
在这里是一个更现实的选择。@MushifAliNawaz计数器很长,因为我们将比较许多学生,而不仅仅是2名学生。我会更新问题我已经回答了你的问题。让我知道它是否有效?