Java实例属性比较引发的一些思考

2023-03-14 09:42:51 浏览数 (2)

Java实例属性比较引发的一些思考

1、缘起

在编写一个判断数据是否变化的逻辑中,比如一个User类,需要比较两个User的实例属性是否全部相同,以此来判断属性值是否已经发生改变。

2、创建测试类

也是较为原始或无脑的写法,举个例子 创建比较的实体类

代码语言:javascript复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private BigDecimal money;
}

编写测试类

代码语言:javascript复制
public class PropertiesTest {

    public static void main(String[] args) {
        // 1、定义两个User实例
        User user1 = new User(1, "zhangsan", new BigDecimal("25.7").setScale(2, RoundingMode.HALF_UP));
        User user2 = new User(1, "zhangsan", new BigDecimal("25.70").setScale(2, RoundingMode.HALF_UP));
        // 2、比较方法
    }
 }
方法一:普通的if-else判断
代码语言:javascript复制
public static void main(String[] args) {
    // 1、定义两个User实例
     User user1 = new User(1, "zhangsan", new BigDecimal("25.7").setScale(2, RoundingMode.HALF_UP));
     User user2 = new User(1, "zhangsan", new BigDecimal("25.70").setScale(2, RoundingMode.HALF_UP));
     boolean flag = compareOne(user1, user2);
     System.out.println(flag);
 }
    
 /**
  * 方法一: 是否if
  * @param user1 实例1
  * @param user2 实例2
  * @return  属性值是否相同
  */
 public static boolean compareOne(User user1, User user2){
     if (!Objects.equals(user1.getId(), user2.getId())) {
         return false;
     } else if (!Objects.equals(user1.getName(), user2.getName())) {
         return false;
     } else return Objects.equals(user1.getMoney(), user2.getMoney());
 }

优点:实体类中需要比较字段较少时,代码逻辑简单。 缺点:实体类中需要比较的字段较多时,代码重复显得冗余。

方法二:通过反射遍历属性字段取得属性值
代码语言:javascript复制
public static void main(String[] args) {
     // 1、定义两个User实例
     User user1 = new User(1, "zhangsan", new BigDecimal("25.7").setScale(2, RoundingMode.HALF_UP));
     User user2 = new User(1, "zhangsan", new BigDecimal("25.70").setScale(2, RoundingMode.HALF_UP));
//        boolean flag = compareOne(user1, user2);
     boolean flag = compareTwo(user1, user2, new String[]{"id", "name", "money"});
     System.out.println(flag);
 }
 
/**
 * 方法二: 使用反射
 * @param user1 实例1
 * @param user2 实例2
 * @return  属性值是否相同
 */
public static boolean compareTwo(User user1, User user2, String[] fields){
    boolean flag = true;
    try {
        for (String field : fields){
            // 实例1
            Field field1 = user1.getClass().getDeclaredField(field);
            field1.setAccessible(true);
            Object value1 = field1.get(user1);
            // 实例2
            Field field2 = user2.getClass().getDeclaredField(field);
            field2.setAccessible(true);
            Object value2 = field2.get(user2);
            if ( !Objects.equals(value1, value2) ) {
                flag = false;
                break;
            }

        }
    } catch (NoSuchFieldException | IllegalAccessException e) {
        flag = false;
        e.printStackTrace();
    }
    return flag;
}

优点:针对于实体类中需要比较字段较多的情况,可以针对封装工具方法。 缺点:实体类中需要比较的字段较多时,反射性能不是较优。

方法三:使用hutool工具

引入hutool工具包

代码语言:javascript复制
<!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all -->
<dependency>
     <groupId>cn.hutool</groupId>
     <artifactId>hutool-all</artifactId>
     <version>5.8.15</version>
</dependency>
代码语言:javascript复制
public static void main(String[] args) {
    // 1、定义两个User实例
    User user1 = new User(1, "zhangsan", new BigDecimal("25.7").setScale(2, RoundingMode.HALF_UP));
    User user2 = new User(1, "zhangsan", new BigDecimal("25.70").setScale(2, RoundingMode.HALF_UP));
//        boolean flag = compareOne(user1, user2);
//        boolean flag = compareTwo(user1, user2, new String[]{"id", "name", "money"});
    boolean flag = compareThree(user1, user2);
    System.out.println(flag);
}

/**
 * 方法三: hutool工具类
 * @param user1 实例1
 * @param user2 实例2
 * @return  属性值是否相同
 */
public static boolean compareThree(User user1, User user2){
    Map<String, Object> map1 = BeanUtil.beanToMap(user1, true, true);
    Map<String, Object> map2 = BeanUtil.beanToMap(user2, true, true);
    if (map1.keySet().size() != map2.keySet().size()) {
        return false;
    }
    for (Map.Entry<String, Object> str : map1.entrySet()){
        if ( !Objects.equals(map2.get(str.getKey()), str.getValue())) {
            return false;
        }
    }
    return true;
}

优点:代码简洁,直接使用第三方工具包接口,比较逻辑简单 缺点:需要引入第三方jar包

总结

以上是对类实例字段值比较的一些思考,希望可以带来一些火花。

0 人点赞