Java集合Map篇

Java学习-05-韩顺平老师

Java-集合Map篇

目录:

01-Map接口
    1.1-Map体系图
    1.2-Map接口特点
    1.3-setEntry、keySet、Values
    1.4-常用方法
    1.5-遍历方法
02-HashMap类
    2.1-基本介绍
    2.2-底层原理
03-Hashtable类
    3.1-基本介绍
    3.2-底层原理
04-HashMap vs Hashtable
05-Properties类
06-如果选择集合实现类

Map接口

Map体系继承图:

在这里插入图片描述

Map接口特点:

注意:这里将的是JDK8的Map接口特点。
1.Map和Collection并列存在。用于保存具有映射关系的数据:Key-Value。
2.Map中的key和value可以是任意引用类型的数据,会封装到HashMap$Node
  对象中。
3.Map中的key不允许重复,其实和HashSet一样。
4.Map的Value可以重复。
5.Map中的key可以为null,value也可以为null,但是key为null,只能有一个。
6.常见的String类作为key。
7.key和value之间存在单向一对一关系,即通过指定的key总能获得value。
8.Map接口常用的实现类:HashMap、Hashtable 和 properties,LinkedHashMap。

entrySet和keySet和Values:

1.k-v 最后是存放在HashMap$Node数组中 Node<K,V>[] newTab = (Node<K,V>[])new Node[newCap];
2.k-v 为了方便程序员遍历,还会创建 EnterySet集合,该集合存放的元素类型是Entry,而Entry对象
  就有k,v EntrySet<Entry<K,V>>。
3.entrySet中定义的是Map.Entry,但实际上存储的还是HashMap$Node,这是因为HashMap$Node 实现了
  Map.Entry接口 
4.所以实际上在entrySet中,元素Entry存放的只是对 table[] 数组的引用,并没有生成新的集合,只是为
  了遍历方便。
5.当把HashMap$Node对象存放到entrySet,之所以方便遍历是Map.Entry提供了获取键key和value的方法
  k getKey() , v getValue() 后面在遍历里面演示。
6.还可以只获得所有的简直对象 KeySet对象实际上是一个Set集合,也可以直接获得值 Values实际上是Collection集合。

常用方法:

1.put:添加。
2.remove:根据键删除映射关系。
3.get:根据键获取值。
4.size:获取元素个数。
5.isEmpty:判断个数是否为0。
6.clear:清空。
7.containsKey:查找键是否存在。

演示代码:采用HashMap(向上转型)演示

public class Map_ {
    public static void main(String[] args) {
        Map map = new HashMap();
        // put
        map.put("张三",10);
        map.put("李四",8);
        map.put("王五",4);
        System.out.println(map); // {李四=8, 张三=10, 王五=4}
        // remove
        map.remove("张三");
        System.out.println(map); // {李四=8, 王五=4}
        // get
        System.out.println(map.get("李四")); // 8
        // size
        System.out.println(map.size()); // 2
        // isEmpty
        System.out.println(map.isEmpty()); // false
        // clear
        map.clear();
        System.out.println(map); // {}
        System.out.println(map.containsKey("张三")); // false
    }
}

遍历方法: 只演示同时取出 key 和 value 的方法,单独取出 value 可以使用 map.Values。

  • 第一种使用 keySet 分别采用 迭代器增强for循环实现。
public class MapErgodic {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("张三",10);
        map.put("李四",8);
        map.put("王五",4);
        Set keys = map.keySet(); // 返回的是一个Set接口对象
        // 采用加强for来实现
        for (Object key : keys) {
            System.out.print( key + " " + map.get(key) + "\t"); // 李四 8	张三 10	王五 4
        }
        // 采用迭代器完成
        Iterator iterator = keys.iterator(); // 获得迭代器
        while (iterator.hasNext()) { // 判断是否有下一个
            Object next = iterator.next();
            System.out.print(next + " " + map.get(next) + "\t"); // 李四 8	张三 10	王五 4
        }
    }
}
  • 第二种使用 entrySet提供的方法实现,同样采用 迭代器增强for循环 实现。
public class MapErgodic {
    public static void main(String[] args) {
        Map map = new HashMap();
        map.put("张三",10);
        map.put("李四",8);
        map.put("王五",4);
        Set entrySet = map.entrySet(); // 获取一个Set对象,存储着多个entry
        // 使用增强for循环
        for (Object obj :entrySet) {
            // 向下转型,因为Map.Entry才有 getKey 和 getValue 方法。
            Map.Entry entry = (Map.Entry)obj;
            System.out.print(entry.getKey() + " " + entry.getValue() + "\t"); // 李四 8	张三 10	王五 4
        }
        // 使用迭代器实现
        Iterator iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            // 同样是向下转型
            Map.Entry entry = (Map.Entry)iterator.next();
            System.out.print(entry.getKey() + " " + entry.getValue() + "\t"); // 李四 8	张三 10	王五 4
        }
    }
}

HashMap类

基本介绍:

1.HashMap是Map接口使用频率最高的实现类。
2.HashMap 是以键值对 key-val对的方式来存储数据[双列](HashMap$Node类型)
3.key 不能重复,但是值可以重复,允许使用null键和null值,但null键只能有一个。
4.如果添加的key相等,则会覆盖原来的key-val 里面的value。
5.和HashSet一样不保证映射关系,底层是以Hash表的方式存储,jdk8以后HashMap底层
  是 数组+链表+红黑树。
6.HashMap没有实现同步,因此线程不安全的,方法没有做同步互斥操作,没有synchronied。

底层原理:

1.HashMap底层维护的是Node类型的数组table,默认初始化为null。
2.当创建对象时,将加载因子(loadfactor)初始化为0.75。
3.当添加key-val时,通过key的哈希值获得在table中的索引,让后判断索引处是否
  有元素,如果没有元素直接添加。如果索引处有元素,继续判断索引处的key值是否
  和要添加元素的key值相等,如果相等,就直接替换val值,如果不相等就循环判断
  该索引处所有链表上有没有相等的key值,如果有就替换val,如果没有就在最后添
  加该元素。
4.第一次添加则需要将table扩容,默认扩容到16个Node节点,临界值(threshold)12
5.以后再进行扩容,扩容机制与HashSet一致,可以具体查看上一篇文章,每次扩容到
  原来的两倍,临界值也根据加载因子随之变化。
6.在java8中,如果一条链表的元素到达个个数超过了TREEIFY_THRESHOLD = 8,
  并且table的大小MIN_TRREEIFY_CAPACITY = 64(默认),就会进行树化,否则
  仍然采用数组扩容机制。

Hashtable类

基本介绍:

1.存放的元素还是键值对 key-val
2.Hashtable的键值都不能为空。
3.Hashtable使用的方法基本上和HashMap一致。
4.Hashtable是线程安全的,实现了方法同步和互斥。

底层原理:

1.底层有数组Hashtable$Entry[] 初始化值为11
2.临界值 threshold 8 = 11 *0.75。
3.扩容: 一旦元素的个数超过临界值,就进行扩容,扩容到原来的2倍加1,
  例如第一次扩容为 2 * 11 + 1 = 23,临界值为 23*0.75=17。
4.执行add 时 实际上是执行了 addEntry(hash,key,value,index),封装成Entry对象。

HashMap vs Hashtable:

线程安全:HashMap 线程不安全,Hashtable线程安全。
效率:HashMap 高 ,Hashtable 较低。
允许null键null值: HashMap允许,Hashtable 不允许。

Properties类

基本介绍:

1.Properties类继承自Hashtable类并实现了接口Map,也是使用键值对的形式存储。
2.他的特点与Hashtable类似。
3.Properties还可以用于从 xxx.properties文件中,加载数据到Properties类对象
  并进行读取和修改。

如果选择集合实现类:

1.判断储存类型(一组对象还是一组键值对):
  一组对象:Collection接口(判断允许重复还是不允许重复)
    允许重复:List
    	增删多:LinkedArrayList(底层维护一个双向链表)
    	查改多:ArrayList(底层维护一个Object类型的可变数组)
    不允许重复:Set
    	无序:HashSet(底层是HashMap,维护一个哈希表,即数组 + 链表 + 红黑树)
    	有序:TreeSet(底层是TreeMap实现了排序功能,可以自定义排序规则)
  一组键值对:Map
    键无序:HashMap(维护一个哈希表,jdk7:数组+链表,jdk8:数组 + 链表 + 红黑树)
    键有序:TreeMap(通过算法实现插入时排序,通过传入一个Comparator匿名内部类对象来实现自定义排序)
    键插入和取出顺序一致:LinkedHashMap
    读取文件:Properties
集合内容学习到此结束,欢迎大家交流学习!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值