`
distantlight1
  • 浏览: 44342 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java类源码学习(2)-HashMap-2

 
阅读更多

本文是上一篇的继续,补全HashMap剩余部分源码

主要是KeySet实现以及一些java8特性方法签名(实现省略了)

    /**
     * 返回键值集合的一个视图
     * 
     * <pre>
     * 实际是实现key集合的一个引用迭代子,HashMap本身的变更可以在keySet中直接反映出来
     * 
     * 如果HashMap在keySet在遍历过程中发生改变(keySet本身的remove除外),则遍历会失败(fast-fail)
     * 
     * 注意keySet不是一个全功能的java.util.Set的实现,仅支持remove、removeAll、retainAll、clear,不支持add、addAll
     * 如果调用add,会抛出UnsupportedOperationException,参见AbstracCollection.add()
     */
    @Override
    public Set<K> keySet() {
        Set<K> ks;
        // 实际返回的就是KeySet,这里判断下只是实现lazy load
        return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
    }

    /**
     * keySet实现内嵌类,基于HashMap本身的。注意不是全功能的set
     */
    final class KeySet extends AbstractSet<K> {

        // 大部分支持的操作直接调用HashMap对应方法
        @Override
        public final int size() {
            return size;
        }

        @Override
        public final void clear() {
            HashMap.this.clear();
        }

        @Override
        public final boolean contains(Object o) {
            return containsKey(o);
        }

        @Override
        public final boolean remove(Object key) {
            return removeNode(hash(key), key, null, false, true) != null;
        }

        /**
         * java8新增的Collection方法实现
         */
        @Override
        public final void forEach(Consumer<? super K> action) {
            Node<K, V>[] tab;
            if (action == null)
                throw new NullPointerException();
            if (size > 0 && (tab = table) != null) {
                int mc = modCount;
                for (int i = 0; i < tab.length; ++i) {
                    for (Node<K, V> e = tab[i]; e != null; e = e.next)
                        action.accept(e.key);
                }

                // 这步是fast-fail特性,这里相当于乐观锁。操作过程中不发生结构变更,才认为才做有效
                if (modCount != mc)
                    throw new ConcurrentModificationException();
            }
        }

        // 迭代子

        @Override
        public final Iterator<K> iterator() {
            return new KeyIterator();
        }

        @Override
        public final Spliterator<K> spliterator() {
            return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
        }

    }

    @Override
    public Collection<V> values() {
    }

    final class Values extends AbstractCollection<V> {
    }

    @Override
    public Set<Map.Entry<K, V>> entrySet() {
    }

    final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
    }

    // java8 的Map default方法的重写,未注释的方法含义都是自明////////////////////////

    @Override
    public V getOrDefault(Object key, V defaultValue) {
    }

    @Override
    public V putIfAbsent(K key, V value) {
    }

    /**
     * key和value都匹配时删除
     */
    @Override
    public boolean remove(Object key, Object value) {
    }

    /**
     * key和value都匹配时,替换为newValue
     */
    @Override
    public boolean replace(K key, V oldValue, V newValue) {
    }

    /**
     * key存在时替换value
     */
    @Override
    public V replace(K key, V value) {
    }

    /**
     * 带默认处理方式的get,如果key存在,则同get,否则就根据mappingFunction计算出value然后put
     */
    @Override
    public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
    }

    /**
     * 相当于回调方式的replace,如果key不存在不做处理。key存在则根据remappingFunction算出新的value,如果为null,则删除,否则替换
     * 
     * @param remappingFunction BiFunction是双参数的Function版本
     */
    @Override
    public
            V
            computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    }

    /**
     * 全功能的compute,apply(k,null)表示k不存在的默认值回调 apply(k,v)表示k存在的replace回调 apply()返回null表示删除节点
     */
    @Override
    public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
    }

    /**
     * 与compute类似,不同是key存在的时候用apply(oldValue,value)来计算(BiFunction全部根据value来)
     */
    @Override
    public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    }

    /**
     * 遍历处理所有元素
     */
    @Override
    public void forEach(BiConsumer<? super K, ? super V> action) {
    }

    /**
     * 双参数版的forEach()
     */
    @Override
    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
    }

    // clone/serialized ///////////////////////

    /**
     * 浅克隆,复制所有kv的引用,不复制kv本身的属性
     */
    @SuppressWarnings("unchecked")
    @Override
    public Object clone() {
        HashMap<K, V> result;
        try {
            result = (HashMap<K, V>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
        result.reinitialize();
        result.putMapEntries(this, false);
        return result;
    }

    final int capacity() {
        return (table != null) ? table.length : (threshold > 0) ? threshold
                : DEFAULT_INITIAL_CAPACITY;
    }

    /**
     * 序列化到流
     *
     * @serialData 4字节capacity+4字节size+(keyObject+valueObject)*
     */
    private void writeObject(java.io.ObjectOutputStream s) throws IOException {
        int buckets = capacity();
        s.defaultWriteObject();
        s.writeInt(buckets);
        s.writeInt(size);
        internalWriteEntries(s);
    }

    // 迭代子 ////////////////////////////////

    /**
     * 基类,注意add是不支持的
     */
    abstract class HashIterator {
        Node<K, V> next; // 下一节点
        Node<K, V> current; // 当前节点
        int expectedModCount; // for fast-fail
        int index; // 当前节点下标

        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) { // fast-fail
                throw new ConcurrentModificationException();
            }
            if (e == null) {
                throw new NoSuchElementException();
            }
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {
                    // 注意遍历次数是Capacity,不是size
                } 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;
            K key = p.key;
            // 迭代子触发删除节点
            removeNode(hash(key), key, null, false, false);
            expectedModCount = modCount;
        }
    }

    /**
     * 遍历Key
     */
    final class KeyIterator extends HashIterator implements Iterator<K> {
    }

    final class ValueIterator extends HashIterator implements Iterator<V> {
    }

    final class EntryIterator extends HashIterator implements Iterator<Map.Entry<K, V>> {
    }

    // 分片迭代子(java8) ///////////////////////

    static class HashMapSpliterator<K, V> {
    }

    static final class KeySpliterator<K, V> extends HashMapSpliterator<K, V> implements
            Spliterator<K> {
    }

    static final class ValueSpliterator<K, V> extends HashMapSpliterator<K, V> implements
            Spliterator<V> {
    }

    static final class EntrySpliterator<K, V> extends HashMapSpliterator<K, V> implements
            Spliterator<Map.Entry<K, V>> {
    }

    // 为LinkedHashMap预留的可重写的方法 //////////////////////

    Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {
        return new Node<>(hash, key, value, next);
    }

    // TreeNode转为普通Node用
    Node<K, V> replacementNode(Node<K, V> p, Node<K, V> next) {
        return new Node<>(p.hash, p.key, p.value, next);
    }

    // 根据kv生成TreeNode,普通node转TreeNode
    TreeNode<K, V> newTreeNode(int hash, K key, V value, Node<K, V> next) {
        return new TreeNode<>(hash, key, value, next);
    }

    // 根据单个普通节点生成TreeNode
    TreeNode<K, V> replacementTreeNode(Node<K, V> p, Node<K, V> next) {
        return new TreeNode<>(p.hash, p.key, p.value, next);
    }

    /**
     * 重置为空表,clone和readObject调用
     */
    void reinitialize() {
        table = null;
        entrySet = null;
        keySet = null;
        values = null;
        modCount = 0;
        threshold = 0;
        size = 0;
    }

    // LinkedHashMap重写的回调
    void afterNodeAccess(Node<K, V> p) {
    }

    void afterNodeInsertion(boolean evict) {
    }

    void afterNodeRemoval(Node<K, V> p) {
    }

    // 序列化表内容
    void internalWriteEntries(java.io.ObjectOutputStream s) throws IOException {
        Node<K, V>[] tab;
        if (size > 0 && (tab = table) != null) {
            for (int i = 0; i < tab.length; ++i) {
                for (Node<K, V> e = tab[i]; e != null; e = e.next) {
                    s.writeObject(e.key);
                    s.writeObject(e.value);
                }
            }
        }
    }

 

分享到:
评论

相关推荐

    基于Java并发编程的concurrency-hashmap-test设计源码

    该项目为基于Java并发编程的ConcurrentHashMap测试设计源码,共包含24个文件,其中Java源文件21个,Git忽略文件1个,Markdown文档1个,XML配置文件1个。内容涵盖并发编程课件代码,适合学习并发编程相关知识。关注...

    java毕业设计项目源码---讯友桌面通讯录

    通过这个项目,我们可以学习到以下几个重要的Java技术和知识点: 1. **Swing GUI框架**:讯友桌面通讯录的界面是由Java Swing库构建的,这是Java用于创建图形用户界面(GUI)的标准库。Swing提供了各种组件,如...

    20-集合框架020-HashMap-1080P 高清-AVC20

    在这个主题中,我们将深入探讨HashMap类,它是Java集合框架中的一个关键组件,特别是在标题“20-集合框架020-HashMap-1080P 高清-AVC20”和描述中所提到的内容。 HashMap是Java.util包中的一个类,它实现了Map接口...

    java毕业设计项目源码---蓝宇快递打印系统

    【Java毕业设计项目源码——蓝宇快递打印系统】是一个基于Java编程语言的软件开发实践,主要用于实现快递公司的打印管理功能。这个系统包含了完整的源代码,对于学习Java编程,特别是针对毕业设计的学生来说,是一个...

    基于Java的实例开发源码-github-Java-api.zip

    2. **集合框架**:Java集合框架包含ArrayList、LinkedList、HashMap等数据结构,方便存储和管理对象。 3. **多线程**:Java.util.concurrent包提供了高级的线程管理和并发工具,如ExecutorService和Semaphore。 4. *...

    app+java+源码-Java-Banking-Application-:JavaBanking的源代码

    JavaBanking是一个基于Java开发的银行应用示例项目,它为理解Java编程语言在实际银行业务场景中的应用提供了很好的学习平台。这个项目包含了完整的源代码,对于初学者和有一定经验的开发者来说,都是一个深入了解...

    java7hashmap源码-Excellent-Blog-share:欢迎分享优秀博客

    hashmap源码 Excellent-Blog-share Welcome to share excellent blogs . 当你的能力还驾驭不了你的目标时,就应该沉下心来历练 当你的才华还撑不起你的野心时,那你就应该静下心来学习 #目录 ###附录 java系列 java8...

    java源码整理包-集合

    在这个“java源码整理包-集合”中,包含了多种核心的集合类的源代码,如`List`、`Map`、`ArrayList`、`HashMap`、`HashSet`、`Hashtable`、`TreeMap`、`TreeSet`和`Vector`。这些源码对于深入理解Java集合的工作原理...

    基于Java的实例开发源码-P2P-多用户在线聊天室(Java源码).zip

    这个Java源码实例对于学习Java网络编程、多线程、GUI设计以及P2P技术具有很高的参考价值。开发者可以通过阅读和理解代码,进一步掌握这些核心概念,并能在此基础上扩展出更多功能,比如文件共享、群聊、语音/视频...

    JAVA实战项目源码-计算机毕业设计java专业-项目源码-项目说明介绍-JAVA+SQL离散数学题库管理系统

    **JAVA实战项目源码-计算机毕业设计java专业-项目源码-项目说明介绍-JAVA+SQL离散数学题库管理系统** 这个项目是一个基于JAVA编程语言和SQL数据库技术的离散数学题库管理系统,专为计算机专业学生设计,适用于毕业...

    java源码和android-17源码

    Java源码和Android 17源码是两个重要的学习资源,对于深入理解Java编程语言以及Android应用程序开发至关重要。这两部分源代码提供了丰富的信息,帮助开发者探究底层实现细节,提升编程技能,解决实际问题。 首先,...

    Java集合专题总结:HashMap 和 HashTable 源码学习和面试总结

    Java集合专题总结:HashMap和HashTable源码学习和面试总结 本文总结了Java集合专题中的HashMap和HashTable,涵盖了它们的源码学习和面试总结。HashMap是一种基于哈希表的集合类,它的存储结构是一个数组,每个元素...

    三套Java基础课件加源码--晋级版

    在本资源包“三套Java基础课件加源码--晋级版”中,你将找到一系列精心设计的Java学习资料,旨在帮助初学者逐步提升技能并深入理解Java编程语言。这个资源包对于那些希望从基础知识开始,逐步进阶的开发者来说是理想...

    深入Java集合学习系列:HashMap的实现原理

    在Java编程语言中,集合框架是开发者日常工作中不可或缺的一部分,HashMap作为其中的重要成员,它的实现原理对于理解Java性能优化和数据结构有深远的意义。HashMap是一个基于哈希表的数据结构,它实现了Map接口,...

    JAVA实战项目源码-计算机毕业设计java专业-项目源码-项目说明介绍-java+applet-家庭理财系统

    《JAVA实战项目源码-家庭理财系统》是一个典型的JAVA编程语言实现的计算机毕业设计项目,旨在帮助学生理解和应用JAVA技术解决实际问题。该项目利用JAVA的强大力量,结合APPLET技术,构建了一个全面的家庭财务管理...

    java类源码-Java-basic-test:Java基础类库源码分析测试用

    这个"Java-basic-test"项目显然专注于Java基础类库的源码分析与测试,这对于深入理解Java的工作原理、学习面向对象编程以及提升编程技能都非常有帮助。下面将详细讨论Java类库中的关键知识点。 1. **Java基础类库**...

    Java 开发-----图书管管理系统(视频+源码).rar

    《Java开发-----图书管管理系统(视频+源码).rar》是一个综合的学习资源,它涵盖了Java编程语言在实际项目中的应用,特别关注于开发一个图书管理系统的全过程。这个压缩包包含了视频教程和完整的源代码,旨在帮助学习...

    java-jdk源码学习

    Java JDK源码学习是深入理解Java编程语言的关键步骤,它能帮助开发者洞悉语言底层的工作原理,提升编程技能和优化代码的能力。JDK(Java Development Kit)是Java开发的核心工具集,包含了Java运行时环境(JRE)、...

    java7hashmap源码-learning-record:学习轨迹记录

    hashmap源码 learning-record - 学习轨迹记录 10月1号 7月18号 基础算法:反转单向链表 7月16号 7月11号 7月9号 复习 : HashTable和HashMap的区别详解 LeetCode 27. 删除元素(Remove Element) 7月8号 7月5号 复习...

    Java实用编程源码50例-迅速提高编程技巧-供初学者学习——供高手参考

    2. **类与对象**:Java的核心是面向对象编程,它通过类来描述对象的属性和行为。初学者可以通过实例了解如何创建、初始化和使用类及对象。 3. **封装、继承与多态**:这是面向对象的三大特性。封装隐藏了对象的内部...

Global site tag (gtag.js) - Google Analytics