java--比较

目录

《一》== 和 equal 比较

《二》comparable 和 comparator比较

《三》两个实体类比较


《一》== 和 equal 比较

java数据的比较可以认为分为两大类:基本数据类型+String常量  VS 引用型数据类型。来个数据类型比较,先定位属于哪一种,然后在对应选择用== 还是用equal 作比较

  • 基本型数据类型+String常量

 

int i=123;
int j=123;
String s1="123";
  • 基本数据类型(byte,short,char,int,float,double,long,boolean)和字符串常量 在方法区中的常量池里面以HashSet策略存储起来的,不管是再多的基本数据 i ,j  或 常量字符s1, 这样的数据都只会存储一个地址,所以 基本型数据类型和常量字符串的比较要有意义只能比较数值,规定用 == 比较数值。
  • 引用型数据类型的==和equal 都用来比较,其中 == 绝对是内存地址比较,equal 就不一定了。默认的超 类Object 中的equal 也是内存地址比较,但是equal 在多处被重写,至于被重写成啥样子,因不同的对象,框架而异。 比如 String 类型中,就用equal 做值比较
  • 备注:String 类型常量,和 new 出来的String 对象,是有区别的。String s1 ="123"; String s2="123"; String s2=new String("123");很明显s1,s2作为字符串常量,内存地址相同即s1==s2【true】,s3 用到new 肯定在内存中重新开辟了另一个空间,所以内存地址不一样了,即s1==s2 !=s3, 但如果做值比较,s1.equals(s2)[true], s1.equals(s3) [true]

《二》comparable 和 comparator比较

comparable 和 comparator 都是接口都可以用来做比较器区别就在于看在什么时候做比较

  1.  如果是新定义一个类时已经知道这个类要做比较的操作,那就用comparable,这样这个类本身就可以作为一个比较器,不用依赖外部处理完成比较功能。
  2. 如果要比较的类时历史的类,动起来代价大,那就不动它,用外部方式处理,这个时候 comparator 就闪亮登场了。
  • comparable 示例
  • package com.example.demo;
    
    /**
     * @author cuitao
     * @ className:
     * @ description:
     * @ create 2021-01-06 19:42
     **/
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    
    /**
     * @desc "Comparator"和“Comparable”的比较程序。
     * (01) "Comparable"
     * 它是一个排序接口,只包含一个函数compareTo()。
     * 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
     * (02) "Comparator"
     * 它是一个比较器接口,包括两个函数:compare() 和 equals()。
     * 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
     * 

    * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。 * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。 */ public class CompareComparatorAndComparableTest { public static void main(String[] args) { // 新建ArrayList(动态数组) ArrayList list = new ArrayList(); // 添加对象到ArrayList中 list.add(new Person("ccc", 20)); list.add(new Person("AAA", 30)); list.add(new Person("bbb", 10)); list.add(new Person("ddd", 40)); // 打印list的原始序列 System.out.println(list.toString()); System.out.println("-------------------------------"); // 对list进行排序 // 这里会根据“Person实现的Comparable接口”进行排序,即会根据“name”进行排序 Collections.sort(list); System.out.println(list.toString()); Arrays.sort(new ArrayList[]{list}); System.out.println(list.toString()); System.out.println("-------------------------------"); } } ========================================================================================= package com.example.demo; /** * @desc Person类。 * Person实现了Comparable接口,这意味着Person本身支持排序,换句话说就是本身有做排序的需求 */ public class Person implements Comparable{ int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return name + " - " +age; } /** * 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等 */ boolean equals(Person person) { if (this.age == person.age && this.name == person.name){ return true;} return false; } /** * @desc 实现 “Comparable” 的接口,即重写compareTo函数。 * 这里是通过“person的名字”进行比较的 */ @Override public int compareTo(Person person) { return name.compareTo(person.name); } }

     

  • comparator 示例
  • 
    import java.util.ArrayList;
    import java.util.Collections;
    
    /**
     * @desc "Comparator"和“Comparable”的比较程序。
     * (01) "Comparable"
     * 它是一个排序接口,只包含一个函数compareTo()。
     * 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
     * (02) "Comparator"
     * 它是一个比较器接口,包括两个函数:compare() 和 equals()。
     * 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
     * 

    * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。 * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。 */ public class CompareComparatorAndComparableTest { public static void main(String[] args) { // 新建ArrayList(动态数组) ArrayList list = new ArrayList(); // 添加对象到ArrayList中 list.add(new Person("ccc", 20)); list.add(new Person("AAA", 30)); list.add(new Person("bbb", 10)); list.add(new Person("ddd", 40)); // 打印list的原始序列 System.out.println(list.toString()); System.out.println("-------------------------------"); // 通过“比较器(AscAgeComparator)”,对list进行排序 // AscAgeComparator的排序方式是:根据“age”的升序排序 Collections.sort(list, new AscAgeComparator()); System.out.println(list.toString()); System.out.println("-------------------------------"); // 通过“比较器(DescAgeComparator)”,对list进行排序 // DescAgeComparator的排序方式是:根据“age”的降序排序 Collections.sort(list, new DescAgeComparator()); System.out.println(list.toString()); } } ================================================================ /** * @desc AscAgeComparator比较器 * 它是“Person的age的升序比较器” */ public class AscAgeComparator implements Comparator { @Override public int compare(Person p1, Person p2) { return p1.getAge() - p2.getAge(); } } ================================================================ import java.util.Comparator; /** * @desc DescAgeComparator比较器 * 它是“Person的age的升序比较器” */ public class DescAgeComparator implements Comparator { @Override public int compare(Person p1, Person p2) { return p2.getAge() - p1.getAge(); } } ================================================================ public class Person { int age; String name; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return name + " - " +age; } /** * 比较两个Person是否相等:若它们的name和age都相等,则认为它们相等 */ boolean equals(Person person) { if (this.age == person.age && this.name == person.name){ return true;} return false; } }

     

《三》两个实体类比较

package com.gildata.task.platform.common.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gildata.task.platform.common.operationLog.TaskPoolConfigLog;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


public class CompareUtil {
    /**
     * 比较两个实体属性值,返回一个boolean,true则表时两个对象中的属性值无差异
     *
     * @param oldObject 进行属性比较的对象1
     * @param newObject 进行属性比较的对象2
     * @return 属性差异比较结果boolean
     */
    public static boolean isDiff(Object oldObject, Object newObject) {
        JSONArray jsonArray = compareFields(oldObject, newObject, null);
        if (jsonArray.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个Map分别存oldObject,newObject此属性名的值
     *
     * @param obj1      进行属性比较的对象1
     * @param obj2      进行属性比较的对象2
     * @param ignoreArr 忽略比较的字段
     * @return 属性差异比较结果map
     */
    @SuppressWarnings("rawtypes")
    public static JSONArray compareFields(Object obj1, Object obj2, String[] ignoreArr) {
        JSONArray jsonArray = new JSONArray();
        try {
            List ignoreList = null;
            if (ignoreArr != null && ignoreArr.length > 0) {
                // array转化为list
                ignoreList = Arrays.asList(ignoreArr);
            }
            if (obj1.getClass() == obj2.getClass()) {// 只有两个对象都是同一类型的才有可比性
                Class clazz = obj1.getClass();
                // 获取object的属性描述
                PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz,
                        Object.class).getPropertyDescriptors();

                for (PropertyDescriptor pd : pds) {// 这里就是所有的属性了
                    String name = pd.getName();// 属性名
                    if (ignoreList != null && ignoreList.contains(name)) {// 如果当前属性选择忽略比较,跳到下一次循环
                        continue;
                    }
                    Method readMethod = pd.getReadMethod();// get方法
                    // 在obj1上调用get方法等同于获得obj1的属性值
                    Object o1 = readMethod.invoke(obj1);
                    // 在obj2上调用get方法等同于获得obj2的属性值
                    Object o2 = readMethod.invoke(obj2);
                    if (o1 instanceof Timestamp) {
                        o1 = new Date(((Timestamp) o1).getTime());
                    }
                    if (o2 instanceof Timestamp) {
                        o2 = new Date(((Timestamp) o2).getTime());
                    }
                    if (o1 == null && o2 == null) {
                        continue;
                    } else if ((o1 == null && o2 != null)) {
                        JSONObject map = new JSONObject();
                        map.put("fieldName", name);
                        map.put("oldValue", "");
                        map.put("newValue", o2);
                        jsonArray.add(map);
                        continue;
                    } else if ((o2 == null && o1 != null)) {
                        JSONObject map = new JSONObject();
                        map.put("fieldName", name);
                        map.put("oldValue", o1);
                        map.put("newValue", "");
                        jsonArray.add(map);
                        continue;
                    }
                    if (!o1.equals(o2)) {
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("fieldName", name);
                        jsonObject.put("oldValue", o1);
                        jsonObject.put("newValue", o2);
                        jsonArray.add(jsonObject);
                    }
                }
            }
            return jsonArray;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        TaskPoolConfigLog taskPoolConfigLog1 = new TaskPoolConfigLog();
        TaskPoolConfigLog taskPoolConfigLog2 = new TaskPoolConfigLog();
        taskPoolConfigLog1.setAppCode("1");
        taskPoolConfigLog2.setAppCode("2");
        taskPoolConfigLog1.setName("张三");
        taskPoolConfigLog2.setAppCode("王五");
        taskPoolConfigLog2.setUpdateTime(new Date());

        String[] ignoreArr = new String[3];
        compareFields(taskPoolConfigLog1, taskPoolConfigLog2, ignoreArr);
    }
}

 

你可能感兴趣的:(java)