JAVA源码学习(一)

1.HashMap

线程不安全。
底层实现:数组+链表/红黑树
数组在HashMap中被称为buckets,每个bucket又存放着由链表中的Node和红黑树中的TreeNode组成的bins。
不论是Node还是TreeNode,它们都是<K,V>形式的泛型类。即Node<K,V>和TreeNode<K,V>,且TreeNode的父类继承自Node,K为用于映射的对象,V为映射对应的值。
HashMap中我们主要关心put和get操作的实现
put操作源码如下:

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    //hash(key)的实现,对hashcode右移16位再自身异或,是为了使hash更加分散
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

其调用了putVal方法

/**
     * Implements Map.put and related methods.
     *
     * @param hash hash for key(key的hash值)
     * @param key the key(要插入的key)
     * @param value the value to put(key对应的值)
     * @param onlyIfAbsent if true, don't change existing value(为true,则不对已存在hashMap中的可以进行修改)
     * @param evict if false, the table is in creation mode.(用于扩展的)
     * @return previous value, or null if none(返回原先存放的值,若不存在则返回null)
     */
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)  //判断table是否为空
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null) //由于n=2^k,故在这里(n-1)&hash等价于hash%n
        	tab[i] = newNode(hash, key, value, null); //如果数组中相应位置为null,则创建新Node
        else {
            Node<K,V> e; K k;
            //以下代码为判断新元素所在的位置
            //1.在数组中
            //2.在红黑树中                         
            //3.在链表中
            //并对每种情况分别处理
            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); //当binCount>TREEIFY_THRESHOLD(默认为8)时链表转换为红黑树
                        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)  //插入元素后判断是否超出 threshold = capacity*loadFactor
            resize();      //n<<=1  capacity扩大两倍,且最大capacity为2^30
        afterNodeInsertion(evict);  //扩展点
        return null;
    }

get操作源码如下

    //使用getNode方法查找key对应的Node,如果查到为
    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

知道了put的流程,那也就大致知道了get的流程

	/**
     * Implements Map.get and related methods.
     *
     * @param hash hash for key
     * @param key the key
     * @return the node, or null if none
     */
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;       //找到数组中对应的Node
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)  //存放在红黑树中
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {            //从链表中获取
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

2.HashTable

线程安全。
线程安全的实现方式:在所有需要保证线程安全的方法头中加上synchronized关键字,即将整个HashTable锁住
底层实现:数组+链表
put和get操作的实现与HashMap大体相同,但无需将链表转换为红黑树

3.ConcurrentHashMap

线程安全。
线程安全的实现方式:对于所有需保证线程安全的方法中,只对数组中某个bucket加锁,采用同步块的方式实现。
底层实现:数组+链表/红黑树
put和get操作的实现与HashMap大体相同,区别在于每次都对key对应的bucket加锁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java码包实例JAVA开发码50个合集: Ajax框架 ZK.rar Java图书馆管理系统程序.rar Java图片倒影效果实例码.rar Java图片翻折,将图像压扁.rar Java坦克大战网络对战版代码.rar Java声音播放程序代码.rar JAVA实现CLDC与MIDP底层编程的代码.rar Java实现HTTP连接与浏览,Java码下载.rar Java实现的FTP连接与数据浏览程序.rar Java实现的放大镜效果附有文件.rar Java实现的点对点短消息发送协议(smpp)开发包码.rar Java实现的视频播放程序码.rar Java实现移动的遮照效果.rar JAVA实现超级玛丽.zip Java实现跟踪鼠标运行坐标的码.rar Java手机与计算机互发彩信码.rar Java手机游戏大富翁代码+注释.rar Java手机短信项目码.rar Java扫雷码.rar Java生成自定义控件代码.rar Java调色板面板代码.rar Java跳棋(基于SWT).rar Java通讯录手机版码.rar Java鼠标拖拽功能.rar 乐趣大型购物系统.rar 可实现网上对战和人机对战.rar 基于BS结构的Java可视化工作流定制软件.rar 基于J2ME的Java游戏梦幻炸弹人程序.rar 基于JAVA的ICQ系统.rar 基于Java的mp3播放器代码.rar 基于Java的小型人事管理系统,带数据库.rar 基于JAVA的日程提醒簿.rar 基于Java的邮件服务器程序.rar 基于MVC的Java管理器 v2.0.rar 基于smpp协议的Java点对点短信发送码包.rar 季风进销存管理系统(JSP版).rar 客户管理系统 Alfresco Content Management.rar 家庭多媒体播放器.rar 局域网广播系统java码.rar 开Winzip压缩工具Java码.rar 很不错的Java计算器.rar 很强的Java加密解密算法码.rar 泡泡堂战车游戏JAVA码.rar 简单模拟的J2ME潜艇大战代码.rar 简单的注册与登录功能.rar 类似QQ的聊天软件JAVA码(附设计文档).rar 进程通信.rar 连接postsql数据库的java代码.rar 附加数据库.rar 雷电游戏JAVA程序.rar

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值