java学习笔记-Map集合中的HashMap集合与Hashtable

目 录

  • HashMap集合(非线程安全的)
    • 两个重要方法put、get(重点)
    • 为什么哈希表的随机增删、查询效率都高?
    • HashMap集合的部分特点
    • HashMap的初始化默认容量
    • 关于HashMap的equals方法和hashCode方法
    • 拓展
  • Hashtable集合(线程安全的)
    • HashTable和HashMap的部分区别
    • HashTable的初始化容量
    • Properties

HashMap集合(非线程安全的)

  1. HashMap集合底层是哈希表/散列表的数据结构(哈希表是一个数组和单向链表的结合体)
  2. HashMap底层有三个值:hash key value next
    (哈希表:是一个一维数组,数组中每个元素是一个单链表)
    java学习笔记-Map集合中的HashMap集合与Hashtable_第1张图片

两个重要方法put、get(重点)

两个重要方法put、get

存:map.put(k,v)实现原理:(掌握)
第一步:先将k,v封装到Node对象中
第二步:底层会调用k的hashCode()方法得出hash值,然后通过哈希算法,将hash值转换成数组的下标,下标位置上如果没有任何元素,就把Node添加到这个位置上。如果下标对应位置上有链表,此时会拿着k和链表上每页节点的k进行equals,如果所有的equals方法返回的都是false,那么这个新节点被添加到这个链表的的末尾。如果其中有一个equals返回的true,那么这个节点value将会被覆盖
 取:v=map.get(k)实现原理:(掌握)
先调用k的hashCode()方法得出哈希值,通过哈希算法转换成数组下标,通过数组下标快速定位到某个位置上,如果这个位置上什么也没有,返回null。如果这个位置上有单链表,那么会拿着参数k和链表上每个节点的k进行equals,如果所有的equals都返回false,那么这个get方法返回null。只要其中有一个k返回true,那么此时这个节点的value就是我们要找的value,get方法最终返回这个节点的value

代码实例:

public class HashMapTest01 {
    public static void main(String[] args) {
        Map<Integer,String> map=new HashMap<>();
        //put方法
        map.put(11,"qwe");
        map.put(22,"asd");
        map.put(33,"zxc");
        map.put(22,"jkl");
        //get方法
        System.out.println(map.get(1));//qwe

		//遍历方法一:(这种对于元素很多的时候效率高)
        //先将Map转成Set
        Set<Map.Entry<Integer,String>> set=map.entrySet();
        //foreach遍历
        for (Map.Entry<Integer,String> entry:set) {
            System.out.println(entry.getKey());
            System.out.println(entry.getValue());
        }

		//遍历方法二:
        //先找key,通过key遍历value
        Set<Integer> set1=map.keySet();
        Iterator<Integer> iterator=set1.iterator();
        while (iterator.hasNext()){
            Integer key=iterator.next();
            String value=map.get(key);
            System.out.println(value);
        }
    }
}

为什么哈希表的随机增删、查询效率都高?

答:因为增删实在链表上完成,查询只是部分查询。

HashMap集合的部分特点

特点:无序,不可重复

为什么无序?
因为元素不一定挂到哪个单链表上

不可重复是怎么保证的?
equals方法保证了HashMap的key不可重复,如果key重复了,value会被覆盖

HashMap的初始化默认容量

初始化默认容量为16,加载因子为0.75f(数组达到75%开始扩容)(Hashset也同样)
扩容后为原容量的:2倍

(注意:HashMap初始化容量为2的倍数)

关于HashMap的equals方法和hashCode方法

放在HashMap集合key部分的元素其实都是放在HashSet集合中了,所以HashSet集合中的元素也需要同时重写hashCode()+equals()方法。
(Tip:如果hashCode()返回是一个固定值,就变成单链表了;如果返回值都不同,就变成一位数组了)
总结:放在HashMap集合的key部分,以及放在HashSet集合中的元素,hashCode()和equals都需要重写!

(注意:如果一个equals重写了,所对应的hashCode也必须重写。
  并且如果equals返回的true,hashCode必须返回相同的值)

拓展

JDK8之后,HashMap的单向链表元素超过8个之后,该单链表会转换成红黑树,若红黑树中元素小于6个,会转换成单链表(为了提高检索效率)。

对于哈希表数据结构来说:
如果两个元素的hash值相同,一定是在同一个单链表上;
如果两个元素的hash值不相同,但由于哈希算法执行结束之后转换的数组下标可能
相同,此时会发生“哈希碰撞”。

Hashtable集合(线程安全的)

Hashtable和HashMap底层都是哈希表数据结构
Hashtable(带有synchronized:线程安全的)(使用较少)

HashTable和HashMap的部分区别

HashTable的key和value都不能为null
HashMap的key和value都可以为null(注意:顶多只能有一个key是null)

HashTable的初始化容量

初始化容量为11,默认加载因子是0.75f
扩容后为原容量的:2倍+1

Properties

Properties是一个Map集合,继承Hashtable
Properties的key和value都是String类型
Properties被称为属性类对象
Properties是线程安全的
Properties代码实例:

public class PropertiesTest01 {
    public static void main(String[] args) {
        //创建Properties对象
        Properties pro=new Properties();
        //存
        pro.setProperty("a","123");
        pro.setProperty("b","456");
        pro.setProperty("c","789");
        //取
        System.out.println(pro.getProperty("a"));
        System.out.println(pro.getProperty("b"));
        System.out.println(pro.getProperty("c"));
    }
}
/*
  输出结果:
    123
    456
    789
*/

你可能感兴趣的:(java学习笔记-Map集合中的HashMap集合与Hashtable)