java集合Map篇——HashTable、TreeMap底层源码

目录

一、HashTable

二、Properties介绍

三、TreeMap 

1.示例代码

2.源码说明 

(1)构造器

(2)添加第一个数据

(3)以后添加数据 

(4)最后一个数据jsp添加失败   


一、HashTable

HashTable是一个继承自Dictionary类的类,它实现了Map接口。HashTable的主要结构是一个Entry数组。

HashMap和HashTable的区别如下:

1. 线程安全性:HashMap是非线程安全的,在多线程环境下可能会出现线程安全问题;而HashTable是线程安全的,大部分方法使用synchronized关键字来确保线程同步,但性能较HashMap低。

2. 允许null值:HashMap的key可以为null(最多一个),value可以为null;HashTable则不允许key和value为null的元素。

3. 继承关系:HashMap继承自AbstractMap,HashTable继承自Dictionary抽象类,两者都实现了Map接口。

4. 初始容量:HashMap的初始容量为16,HashTable的初始容量为11。

5. 扩容机制:HashMap的扩容为原来的两倍,HashTable的扩容为两倍+1。

6. 红黑树转换:HashTable不会转换为红黑树。

另外个作者的部分源码说明HashTable底层实现-CSDN博客

二、Properties介绍

1.Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存数据。

2.他的使用特点和Hashtable类似

3.Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象并进行读取和修改

4.工作后xxx.properties文件通常作为配置文件,配合IO使用

https://www.cnblogs.com/xudong-bupt/p/3758136.html

三、TreeMap 

TreeMap的底层还是维护的是红黑树,与HashMap不同的是每一个节点是Entry类型。

一般使用TreeMap要自己指定规定的比较器 

直接上示例:

1.示例代码

public class TreeMapType {
    public static void main(String[] args) {
        TreeMap<String, String> treeMap = new TreeMap<>(new Comparator<String>() {
            //通过匿名内部类的方法实现Comparator定义比较规则
            @Override
            public int compare(String o1, String o2) {
                return o1.length() - o2.length();
            }
        });
        treeMap.put("java", "a");
        treeMap.put("apple", "b");
        treeMap.put("orange", "c");
        treeMap.put("php", "d");
        treeMap.put("jsp", "e");//没有加入,因为通过比较器比较长度相同
        System.out.println(treeMap);
    }
}

输出结果

 

2.源码说明 

添加元素的主要方法

    /**
     * 将指定的值与该映射中的指定键关联。如果映射中之前已存在此键的映射关系,
     * 则替换旧值。
     *
     * @param key 要将指定值与之关联的键
     * @param value 要与指定键关联的值
     *
     * @return 此键前一个关联的值,或 null(如果不存在此键的映射)。
     *         (null 返回也可以表示映射之前将 null 与 key 关联)
     * @throws ClassCastException 如果指定的键无法与映射中当前的键进行比较
     * @throws NullPointerException 如果指定的键为 null,且此映射使用自然排序,
     *         或其比较器不允许 null 键
     */

    public V put(K key, V value) {
        // 获取根节点
        Entry<K,V> t = root;
        // 如果树为空,初始化根节点
        if (t == null) {
            // 检查类型(可能还有 null 值)
            compare(key, key); 

            // 创建新的根节点并设置大小和修改计数
            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null; // 返回 null,因为没有旧值可以替换
        }

        int cmp;
        Entry<K,V> parent;
        //以后添加数据
        // 根据是否有比较器来区分处理路径
        Comparator<? super K> cpr = comparator;
        if (cpr != null) {
            // 使用比较器搜索插入位置
            do {//遍历所有的key,给当前key找到适当位置
                parent = t;
                cmp = cpr.compare(key, t.key);//动态绑定到我们的匿名内部类的compare
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else//如果遍历过程中,发现准备添加Key和当前已有的Key相等,就不添加
                    return t.setValue(value); // 如果找到键,则替换值并返回旧值
            } while (t != null);
        }
        else {
            // 如果键为 null,抛出异常,因为此映射不接受 null 键
            if (key == null)
                throw new NullPointerException();
            // 使用键的自然顺序进行比较
            @SuppressWarnings("unchecked")
            Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value); // 如果找到键,则替换值并返回旧值
            } while (t != null);
        }

        // 创建新节点并确定其插入位置
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;

        // 插入后维护红黑树规则
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null; // 返回 null,因为没有旧值可以替换
    }

(1)构造器

传入的实现了Comparator接口的匿名内部类(对象),传给给TreeMap的comparator属性

 

(2)添加第一个数据

第一次添加,把k-v封装到Entry对象,放入root

(3)以后添加数据 

(4)最后一个数据jsp添加失败   

在循环中遍历到长度相同的数据php,插入失败

因为比较器比较的就只有长度。 

将旧值覆盖  d ——>e 

 

 

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值