• java——HashSet中add()方法不能加重复值得原因理解(我们一起来看底层代码吧)


    Set<String> names = new HashSet<>();
            names.add("张三");
            names.add(new String("张三"));
            
            Iterator<String> iterator = names.iterator();
            while(iterator.hasNext()) {
                System.out.println(iterator.next());
            }

    以上代码输出只有一个:张三

    惊不惊喜,意不意外???

    下面我们来看原因

    按住ctrl键点击add进入到public interface Set<E> extends Collection<E> Set接口中的add抽象方法

    boolean add(E e);

    然后按住ctrl键盘点击到HashSet类中重新的add方法

     public boolean add(E e) {
            return map.put(e, PRESENT)==null;
        }

    按住ctrl键点击put  进入到HashMap类中的put方法

      public V put(K key, V value) {
            return putVal(hash(key), key, value, false, true);
        }

    其中的hash(key)是HashMap中的方法

    static final int hash(Object key) {
            int h;
            return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
        }

    返回的值是key.hashCode()的相关转换,我们就看key.hashCode()的值是什么了  那我们来看一下这个方法

        public native int hashCode();//是Object类中的一个抽象方法

    其中有继承重写这个方法的,但是打开Eclipse就会bug 试了两次了  ,那我们就不打开了

    但是我们可以得到一个结论

    本身HashSet中的hashCode()方法就是同一个对象的hashCode()的返回值是相等的

    我们可以自己重写hashCode()方法来判断他返回的值

    并且其中putVal()方法也在HashMap方法中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;
          /*
          怎么判断相等的就是用下面的红色代码
            p.hash==hash 就是调用hash(key)方法后的值,只要是同一个对象,返回值就相同(可以重写hashCode()方法)
        
            (k = p.key) == key判断两个对象的地址是否相同
            
              key.equals(k)默认调用Object类中的equals方法判断地址是否相同,可以重写equals方法
            如果以上满足
                if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(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; }

    分析:为上面青色字体

  • 相关阅读:
    挑战练习题2.3动态规划 poj1631 Bridging signals 最长递增子序列
    挑战练习题2.3动态规划 poj1065 Wooden Sticks 最长递减子序列
    挑战练习题2.3动态规划 poj3181 Dollar Dayz 完全背包
    挑战练习题2.3动态规划 poj3046 Ant Counting dp
    挑战练习题2.3动态规划 poj1742 Coins 多重背包
    挑战练习题2.3动态规划 poj3280Cheapest Palindrome 区间dp
    Matplotlib
    Bar-Code-Recognition-System Private
    图像处理项目——基于机器视觉技术的条形码在线识别系统设计
    github的使用
  • 原文地址:https://www.cnblogs.com/lyxcode/p/9454139.html
Copyright © 2020-2023  润新知