• 大杂烩 -- equals、hashCode联系与区别


    基础大杂烩 -- 目录

    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

    Equals

    1、默认情况(没有覆盖equals方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。

        public boolean equals(Object obj) {
            return (this == obj);
        }

    2 、如果类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。

        @Override
        public boolean equals(Object obj) {
            // 1.地址相等
            if (this == obj)
                return true;
            // 2.不为空
            if (obj == null)
                return false;
            // 3.类型相同
            if (getClass() != obj.getClass())
                return false;
            StudentOverrideEquals other = (StudentOverrideEquals) obj;
            // 4.属性相等
            if (age != other.age)
                // 4.1基本数据类型判断值
                return false;
            // 4.2引用数据类型。1.空值判断,2.非空调用自身equals()
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }

    HashCode

    1.默认情况(没有覆盖hashCode方法)下hashCode方法都是调用Object类的hashCode方法,而Object的hashCode方法的返回值的默认实现是根据对象的内存地址进行计算。

        public native int hashCode();

    2.如果类中覆盖了hashCode方法,那么就要根据具体的代码来确定hashCode方法的返回值,覆盖后一般都是通过对象的属性计算hashCode值。

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }

    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

    不覆写equals、不覆写hashCode(Tt02)

       覆写equals、不覆写hashCode(Tt03)

    不覆写equals、   覆写hashCode(Tt04)

       覆写equals、   覆写hashCode(Tt05)

       覆写equals、   覆写hashCode(返回值不同)(Tt06)

    -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

    Tt02:不覆写equals、不覆写hashCode

    Class : Student

    package limeMianShi.duolaidian.equals_hashcode;
    
    /**
     * 没有覆盖equals、hashCode方法
     * 
     * @author lime
     *
     */
    public class Student {
    
        private String name;
        private int age;
        public Student() {
            super();
        }
        public Student(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 没有覆盖equals、hashCode方法
     * 
     * @author lime
     *
     */
    public class Test02 {
    
        public static void main(String[] args) {
            List<Student> list = new LinkedList<Student>();
            Set<Student> set = new HashSet<Student>();
            Student stu1 = new Student("lime",25);
            Student stu2 = new Student("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : false
    stu1-->HashCode:1865127310
    stu2-->HashCode:515132998
    list size:2
    set size:2

    Tt03:覆写equals、不覆写hashCode

    Class : StudentOverrideEquals

    package limeMianShi.duolaidian.equals_hashcode;
    
    /**
     * 覆写equals方法
     * 
     * @author lime
     *
     */
    public class StudentOverrideEquals {
    
        private String name;
        private int age;
    
        public StudentOverrideEquals() {
            super();
        }
    
        public StudentOverrideEquals(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public boolean equals(Object obj) {
            // 1.地址相等
            if (this == obj)
                return true;
            // 2.不为空
            if (obj == null)
                return false;
            // 3.类型相同
            if (getClass() != obj.getClass())
                return false;
            StudentOverrideEquals other = (StudentOverrideEquals) obj;
            // 4.属性相等
            if (age != other.age)
                // 4.1基本数据类型判断值
                return false;
            // 4.2引用数据类型。1.空值判断,2.非空调用自身equals()
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 覆写equals方法
     * 
     * @author lime
     *
     */
    public class Test03 {
    
        public static void main(String[] args) {
            List<StudentOverrideEquals> list = new LinkedList<StudentOverrideEquals>();
            Set<StudentOverrideEquals> set = new HashSet<StudentOverrideEquals>();
            StudentOverrideEquals stu1 = new StudentOverrideEquals("lime",25);
            StudentOverrideEquals stu2 = new StudentOverrideEquals("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    stu1-->HashCode:1865127310
    stu2-->HashCode:515132998
    list size:2
    set size:2

    Tt04:不覆写equals、覆写hashCode

    Class : StudentOverrideHashCode

    package limeMianShi.duolaidian.equals_hashcode;
    
    
    /**
     * 覆盖hashCode方法
     * 
     * @author lime
     *
     */
    public class StudentOverrideHashCode {
    
        private String name;
        private int age;
        public StudentOverrideHashCode(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public StudentOverrideHashCode() {
            super();
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 覆写hashCode方法
     * 
     * @author lime
     *
     */
    public class Test04 {
    
        public static void main(String[] args) {
            List<StudentOverrideHashCode> list = new LinkedList<StudentOverrideHashCode>();
            Set<StudentOverrideHashCode> set = new HashSet<StudentOverrideHashCode>();
            StudentOverrideHashCode stu1 = new StudentOverrideHashCode("lime",25);
            StudentOverrideHashCode stu2 = new StudentOverrideHashCode("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : false
    stu1-->HashCode:3323549
    stu2-->HashCode:3323549
    list size:2
    set size:2

    Tt05:覆写equals、覆写hashCode

    Class : StudentOverrideEqualsHashCode

    package limeMianShi.duolaidian.equals_hashcode;
    
    /**
     * 覆盖equals 和 hashCode方法
     * 
     * @author lime
     *
     */
    public class StudentOverrideEqualsHashCode {
    
        private String name;
        private int age;
        public StudentOverrideEqualsHashCode(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public StudentOverrideEqualsHashCode() {
            super();
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            StudentOverrideEqualsHashCode other = (StudentOverrideEqualsHashCode) obj;
            if (age != other.age)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 覆写equals、hashCode方法
     * 
     * @author lime
     *
     */
    public class Test05 {
    
        public static void main(String[] args) {
            List<StudentOverrideEqualsHashCode> list = new LinkedList<StudentOverrideEqualsHashCode>();
            Set<StudentOverrideEqualsHashCode> set = new HashSet<StudentOverrideEqualsHashCode>();
            StudentOverrideEqualsHashCode stu1 = new StudentOverrideEqualsHashCode("lime",25);
            StudentOverrideEqualsHashCode stu2 = new StudentOverrideEqualsHashCode("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    stu1-->HashCode:3323549
    stu2-->HashCode:3323549
    list size:2
    set size:1

    Tt05:覆写equals、覆写hashCode(返回值不同)

    Class : StudentOverrideEqualsHashCodeneq

    package limeMianShi.duolaidian.equals_hashcode;
    
    /**
     * equals 相等,hashCode不等
     * 
     * @author lime
     *
     */
    public class StudentOverrideEqualsHashCodeneq {
    
        private String name;
        private int age;
        public StudentOverrideEqualsHashCodeneq(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public StudentOverrideEqualsHashCodeneq() {
            super();
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public int hashCode() {
            return (int) (Math.random()*10);
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            StudentOverrideEqualsHashCodeneq other = (StudentOverrideEqualsHashCodeneq) obj;
            if (age != other.age)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 覆写equals、hashCode(返回值不同)方法
     * 
     * @author lime
     *
     */
    public class Test06 extends Object{
    
        public static void main(String[] args) {
            List<StudentOverrideEqualsHashCodeneq> list = new LinkedList<StudentOverrideEqualsHashCodeneq>();
            Set<StudentOverrideEqualsHashCodeneq> set = new HashSet<StudentOverrideEqualsHashCodeneq>();
            StudentOverrideEqualsHashCodeneq stu1 = new StudentOverrideEqualsHashCodeneq("lime",25);
            StudentOverrideEqualsHashCodeneq stu2 = new StudentOverrideEqualsHashCodeneq("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    stu1-->HashCode:1
    stu2-->HashCode:6
    list size:2
    set size:2

    Tt07:覆写equals、覆写hashCode(修改属性值,改变hashCode,remove)

    Class :StudentOverrideEqualsHashCode

    package limeMianShi.duolaidian.equals_hashcode;
    
    /**
     * 覆盖equals 和 hashCode方法
     * 
     * @author lime
     *
     */
    public class StudentOverrideEqualsHashCode {
    
        private String name;
        private int age;
        public StudentOverrideEqualsHashCode(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public StudentOverrideEqualsHashCode() {
            super();
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            StudentOverrideEqualsHashCode other = (StudentOverrideEqualsHashCode) obj;
            if (age != other.age)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    }

    Class : main

    package limeMianShi.duolaidian.equals_hashcode;
    
    import java.util.HashSet;
    import java.util.LinkedList;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 覆写equals、hashCode方法。修改参与计算hashCode的属性
     * 
     * @author lime
     *
     */
    public class Test07{
    
        public static void main(String[] args) {
            List<StudentOverrideEqualsHashCode> list = new LinkedList<StudentOverrideEqualsHashCode>();
            Set<StudentOverrideEqualsHashCode> set = new HashSet<StudentOverrideEqualsHashCode>();
            StudentOverrideEqualsHashCode stu1 = new StudentOverrideEqualsHashCode("lime",25);
            StudentOverrideEqualsHashCode stu2 = new StudentOverrideEqualsHashCode("lime", 25);
            System.out.println("stu1 == stu2 : "+(stu1 == stu2)); 
            System.out.println("stu1.equals(stu2) : "+stu1.equals(stu2));
            
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            System.out.println("stu2-->HashCode:" + stu2.hashCode());
            
            list.add(stu1);
            list.add(stu2);
            System.out.println("list size:"+ list.size());
            
            set.add(stu1);
            set.add(stu2);
            System.out.println("set size:"+ set.size());
            
            System.out.println("修改stu1的name");
            stu1.setName("oracle");
            System.out.println("stu1-->HashCode:" + stu1.hashCode());
            set.remove(stu1);
            System.out.println("set size:"+ set.size());
        }
    }

    Console : 

    stu1 == stu2 : false
    stu1.equals(stu2) : true
    stu1-->HashCode:3323549
    stu2-->HashCode:3323549
    list size:2
    set size:1
    修改stu1的name
    stu1-->HashCode:-1008860090
    set size:1

    结果分析:

    set添加元素时,首先判断hashCode一致,在判断equals一致。

    set移除元素时,首先判断hashCode一致,根据hashCode移除元素。

    当我们将某个对象存到set中时,如果该对象的属性参与了hashcode的计算,那么以后就不能修改该对象参与hashcode计算的那些属性了,否则会引起意向不到的错误的。正如测试中,不能够移除stu1对象。

    hashSet本质是封装hashMap

    package java.util;
    
    import java.io.InvalidObjectException;
    
    public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable{
    
        static final long serialVersionUID = -5024744406713321676L;
    
        private transient HashMap<E,Object> map;
    
        private static final Object PRESENT = new Object();
    
        public HashSet() {
            map = new HashMap<>();
        }
    
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
    
        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
    
        public HashSet(int initialCapacity) {
            map = new HashMap<>(initialCapacity);
        }
    
        HashSet(int initialCapacity, float loadFactor, boolean dummy) {
            map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }
    
        public Iterator<E> iterator() {
            return map.keySet().iterator();
        }
    
        public int size() {
            return map.size();
        }
    
        public boolean isEmpty() {
            return map.isEmpty();
        }
    
        public boolean contains(Object o) {
            return map.containsKey(o);
        }
    
        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
    
        public boolean remove(Object o) {
            return map.remove(o)==PRESENT;
        }
    
        public void clear() {
            map.clear();
        }
    
        @SuppressWarnings("unchecked")
        public Object clone() {
            try {
                HashSet<E> newSet = (HashSet<E>) super.clone();
                newSet.map = (HashMap<E, Object>) map.clone();
                return newSet;
            } catch (CloneNotSupportedException e) {
                throw new InternalError(e);
            }
        }
    
        private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
            s.defaultWriteObject();
    
            s.writeInt(map.capacity());
            s.writeFloat(map.loadFactor());
    
            s.writeInt(map.size());
    
            for (E e : map.keySet())
                s.writeObject(e);
        }
    
        private void readObject(java.io.ObjectInputStream s)
            throws java.io.IOException, ClassNotFoundException {
            s.defaultReadObject();
    
            int capacity = s.readInt();
            if (capacity < 0) {
                throw new InvalidObjectException("Illegal capacity: " + capacity);
            }
    
            float loadFactor = s.readFloat();
            if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
                throw new InvalidObjectException("Illegal load factor: " +
                                                 loadFactor);
            }
    
            int size = s.readInt();
            if (size < 0) {
                throw new InvalidObjectException("Illegal size: " +
                                                 size);
            }
    
            capacity = (int) Math.min(size * Math.min(1 / loadFactor, 4.0f), HashMap.MAXIMUM_CAPACITY);
    
            map = (((HashSet<?>)this) instanceof LinkedHashSet ?
                   new LinkedHashMap<E,Object>(capacity, loadFactor) :
                   new HashMap<E,Object>(capacity, loadFactor));
    
            for (int i=0; i<size; i++) {
                @SuppressWarnings("unchecked")
                    E e = (E) s.readObject();
                map.put(e, PRESENT);
            }
        }
    
        public Spliterator<E> spliterator() {
            return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0);
        }
    }

    set-->add:

        public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }
        public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);
        }

    set-->remove : 

        public boolean remove(Object o) {
            return map.remove(o)==PRESENT;
        }
        public V remove(Object key) {
            Node<K,V> e;
            return (e = removeNode(hash(key), key, null, false, true)) == null ?
                null : e.value;
        }

    总结:

    1、equals方法用于比较对象的内容是否相等(覆盖以后)

    2、hashcode方法只有在集合中用到

    3、当覆盖了equals方法时,比较对象是否相等将通过覆盖后的equals方法进行比较(判断对象的内容是否相等)。

    4、将对象放入到集合中时,首先判断要放入对象的hashcode值与集合中的任意一个元素的hashcode值是否相等,如果不相等直接将该对象放入集合中。如果hashcode值相等,然后再通过equals方法判断要放入对象与集合中的任意一个对象是否相等,如果equals判断不相等,直接将该元素放入到集合中,否则不放入。

    5、将元素放入集合的流程图:

    啦啦啦

    啦啦啦

  • 相关阅读:
    CSS学习(五)
    1. Git-2.12.0-64-bit .exe下载
    90.bower解决js的依赖管理
    89.[NodeJS] Express 模板传值对象app.locals、res.locals
    88.NODE.JS加密模块CRYPTO常用方法介绍
    87.node.js操作mongoDB数据库示例分享
    50.AngularJs directive详解及示例代码
    49.AngularJs 指令directive之controller,link,compile
    48.AngularJS ng-src 指令
    86.express里面的app.configure作用
  • 原文地址:https://www.cnblogs.com/ClassNotFoundException/p/7008173.html
Copyright © 2020-2023  润新知