• Java_map的key为自定义对象


    首先自定义Key对象

    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.Setter;
    
    import java.util.Objects;
    
    /**
     * @author AganRun
     * @date 2019/10/16
     */
    @Getter
    @Setter
    @AllArgsConstructor
    public class SelfKey {
    
        private String first;
        private String second;
        private String third;
    
        @Override
        public int hashCode() {
            return first.hashCode() + second.hashCode() + third.hashCode();
        }
    
        @Override
        public boolean equals(Object obj) {
    //        super.equals(obj);
            SelfKey selfKey = (SelfKey) obj;
            boolean equals1 = Objects.equals(this.first, selfKey.getFirst());
            boolean equals2 = Objects.equals(this.second, selfKey.getSecond());
            boolean equals3 = Objects.equals(this.third, selfKey.getThird());
            return equals1 && equals2 && equals3;
        }
    }
    
    

    测试类

    import lombok.extern.slf4j.Slf4j;
    import org.junit.Test;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author AganRun
     * @date 2019/10/16
     */
    @Slf4j
    public class HashMapSelfKeyTest {
    
        @Test
        public void test(){
            SelfKey selfKey1 = new SelfKey("1","2","3");
            SelfKey selfKey2 = new SelfKey("3","2","1");
    
            Map<SelfKey, String> map = new HashMap<>();
            map.put(selfKey1, "value1");
            map.put(selfKey2, "value2");
    
            /**
             * 如果不重写hashcode和equals方法,至于put时的对象可以取出对应的值
             * 第一个输出:06:53:50.193 [main] INFO com.agan.map.HashMapSelfKeyTest - null
             * 第二个输出:06:53:50.195 [main] INFO com.agan.map.HashMapSelfKeyTest - value1
             *
             * 如果只重写hashCode方法。equals比较时依旧比较内存地址,导致不通过
             * 输出结果和第一个相同
             *
             * 自定义重写了hashCode和Equeals方法后
             * 07:02:47.469 [main] INFO com.agan.map.HashMapSelfKeyTest - value1
             * 07:02:47.472 [main] INFO com.agan.map.HashMapSelfKeyTest - value1
             */
            log.info(map.get(new SelfKey("1", "2", "3")));
            log.info(map.get(selfKey1));
        }
    }
    
    

    在这里再写两个其他的发现。
    equals在程序执行时可能会调用多次,比如可以在equals中打印语句。

    toString方法会调用这个方法的HashCode()方法

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
    

    HashMap的判断

    如果hash值mod之后的索引,索引冲突后会看key是否相同,如果相同则不再比较,如果不同再比较equals

    
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
        
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                       boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
    
  • 相关阅读:
    RHCE考试要求
    c语言:md5函数
    c语言:计算输入字符个数
    IP数据报之Internet Header Length
    常用的tar和rpm命令参数
    Oracle数据库实例的创建、删除、修改【转载】
    Internal类或Internal成员讲解
    序列化与反序列化 BinaryFormatter.Serialize 方法 (Stream, Object)
    oracle网络配置listener.ora、sqlnet.ora、tnsnames.ora
    Oracle启动模式及其常见问题探讨
  • 原文地址:https://www.cnblogs.com/AganRun/p/11816032.html
Copyright © 2020-2023  润新知