专注、坚持

日拱一卒 - 21.08.11 & 08.12

2021.08.13 by kingcos
Preface · 序
公众号内容同步备份。
  • 本篇文章首发自我的公众号:

萌面大道


Life

  • 🎵 太阳照常升起 - 久石让

先对点进文章却发现内容被删除的读者说句抱歉,昨晚的文章由于我忘记注意标题,导致带着个「未命名文章」的标题就发出了。尝试挽救未果,还是做了删除的决定,合并入今天的内容中一起发布,实在抱歉。

光,也许是最好的滤镜:

210702 🏗

但,也少不了风雨:

210705 🌧️

风雨总会过去,也感谢朋友在那晚来地铁站为我送伞。

210705 No Vendors*

*vendor:n. 小贩;摊贩

今天看到 Set 集合一章,集合的特点是无序、唯一。虽然不能用下标(类似数组)的方式去遍历集合的元素,但我们仍然可以用迭代器、for-in 循环来遍历。所以我就和朋友讨论集合的遍历是如何实现的

因为朋友是 Java 后端工程师,而我也恰好略微了解点,所以这里以 Java 为例。Java 里的 Setinterface 即接口,具体实现则是 HashSet,我们可以查到后者的实现源码。原来 HashSet 只是一层壳,其底层仍然是大名鼎鼎的 HashMap

// HashSet.java from OpenJDK-16

public Iterator<E> iterator() {
    return map.keySet().iterator();
}

这里不去深究细节(其实是我也不会),说说我的个人理解:HashMap 的实现方案是数组与链表(或红黑树)的结合。当出现哈希冲突时,采取链表(或红黑树)的形式存储(数组中存放头节点),其中存储的类型是 Map.Entry<K,V> 即键值对。HashSet 则是不关心值的 HashMap,相当于把集合中的值作为键存储在了底层的 HashMap 中。因此其实 HashSet 还是把内容存储在了数组与链表(或红黑树)的结合中,但存储的顺序并不是按照索引自增,而是根据哈希值,遍历则也就是遍历该数组与链表(或红黑树)的结合即可,核心源码如下:

// HashMap.java from OpenJDK-16

abstract class HashIterator {
    Node<K,V> next;        // next entry to return
    Node<K,V> current;     // current entry
    int expectedModCount;  // for fast-fail
    int index;             // current slot

    HashIterator() {
        expectedModCount = modCount;
        Node<K,V>[] t = table;
        current = next = null;
        index = 0;
        if (t != null && size > 0) { // advance to first entry
            do {} while (index < t.length && (next = t[index++]) == null); // 🌟
        }
    }

    public final boolean hasNext() {
        return next != null;
    }

    final Node<K,V> nextNode() {
        Node<K,V>[] t;
        Node<K,V> e = next;
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        if (e == null)
            throw new NoSuchElementException();
        if ((next = (current = e).next) == null && (t = table) != null) {
            do {} while (index < t.length && (next = t[index++]) == null); // 🌟
        }
        return e;
    }

    public final void remove() {
        Node<K,V> p = current;
        if (p == null)
            throw new IllegalStateException();
        if (modCount != expectedModCount)
            throw new ConcurrentModificationException();
        current = null;
        removeNode(p.hash, p.key, null, false, false);
        expectedModCount = modCount;
    }
}

final class KeyIterator extends HashIterator
    implements Iterator<K> {
    public final K next() { return nextNode().key; }
}

不过以上仅是班门弄斧,若表述或者分析得有问题,还望批评指出,不胜感激。

Code & Notes

可详见《Advanced Swift》笔记一文。

这一周过得可真快。晚安,明天见~

阅读原文