java--comparison

table of Contents

《一》== Compare with equal

Comparison of Comparable and Comparator

Comparison of Two Entity Classes in "Three"


《一》== Compare with equal

The comparison of java data can be considered to be divided into two categories: basic data types + String constants VS reference data types. To compare the data types, first locate which one it belongs to, and then choose whether to use == or equal for comparison.

  • Basic data type + String constant

 

int i=123;
int j=123;
String s1="123";
  • The basic data types (byte, short, char, int, float, double, long, boolean) and string constants are stored in the constant pool in the method area with the HashSet strategy, no matter how much basic data i, j or Constant character s1, such data will only store one address, so the comparison of basic data type and constant string can only compare values ​​if it is meaningful. It is stipulated to use == to compare values.
  • Reference data types == and equal are both used for comparison, where == is definitely a memory address comparison, and equal is not necessarily . The equal in the default superclass Object is also a memory address comparison, but equal has been rewritten in many places. As for how it is rewritten, it differs for different objects and frameworks. For example, in the String type, equal is used for value comparison .
  • Remarks: String constants are different from the String objects produced by new. String s1 ="123"; String s2="123"; String s2=new String("123"); Obviously s1, s2 are string constants, and the memory address is the same, namely s1==s2[true], s3 is used new must reopen another space in the memory, so the memory address is different, that is, s1==s2 !=s3, but if you compare values, s1.equals(s2)[true], s1.equals(s3) [true]

Comparison of Comparable and Comparator

Comparable and comparator are both interfaces , and both can be used as comparators . The difference lies in when to compare .

  1.  If you already know when you define a new class that the class needs to be compared, use comparable, so that the class itself can be used as a comparator without relying on external processing to complete the comparison function.
  2. If the class to be compared is a historical class, which is expensive to move, then leave it alone and handle it in an external way. At this time, the comparator will come on stage.
  • comparable example
  • 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接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
     * <p>
     * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。
     * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
     */
    public class CompareComparatorAndComparableTest {
    
        public static void main(String[] args) {
            // 新建ArrayList(动态数组)
            ArrayList<Person> list = new ArrayList<Person>();
            // 添加对象到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<String>接口”进行排序,即会根据“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<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;
        }
    
        /**
         * @desc 实现 “Comparable<String>” 的接口,即重写compareTo<T t>函数。
         *  这里是通过“person的名字”进行比较的
         */
        @Override
        public int compareTo(Person person) {
            return name.compareTo(person.name);
        }
    }
    
    

     

  • comparator example
  • 
    import java.util.ArrayList;
    import java.util.Collections;
    
    /**
     * @desc "Comparator"和“Comparable”的比较程序。
     * (01) "Comparable"
     * 它是一个排序接口,只包含一个函数compareTo()。
     * 一个类实现了Comparable接口,就意味着“该类本身支持排序”,它可以直接通过Arrays.sort() 或 Collections.sort()进行排序。
     * (02) "Comparator"
     * 它是一个比较器接口,包括两个函数:compare() 和 equals()。
     * 一个类实现了Comparator接口,那么它就是一个“比较器”。其它的类,可以根据该比较器去排序。
     * <p>
     * 综上所述:Comparable是内部比较器,而Comparator是外部比较器。
     * 一个类本身实现了Comparable比较器,就意味着它本身支持排序;若它本身没实现Comparable,也可以通过外部比较器Comparator进行排序。
     */
    public class CompareComparatorAndComparableTest {
    
        public static void main(String[] args) {
            // 新建ArrayList(动态数组)
            ArrayList<Person> list = new ArrayList<Person>();
            // 添加对象到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<Person> {
    
        @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<Person> {
    
        @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;
        }
    
    }
    
    

     

Comparison of Two Entity Classes in "Three"

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<String> 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);
    }
}

 

Guess you like

Origin blog.csdn.net/CUITAO2305532402/article/details/112292433