Java Map接口及其实现类原理解析

Map接口

Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value;

Map中的键值对以Entry类型的对象实例形式存在;
建(key值)不可重复,value值可以重复,一个value值可以和很多key值形成对应关系,每个建最多只能映射到一个值。

Map支持泛型,形式如:Map<K,V>

Map中使用put(K key,V value)方法添加

Map接口中定义的常用方法

具体使用在实现类中讨论

int size();//获取Map集合大小(即元素数量)
boolean isEmpty();//判断是否为空
boolean containsKey(Object key);//判断是否包含某个键
boolean containsValue(Object value);//判断是否包含某个值
V get(Object key);//获取某个键对应的值
V put(K key, V value);//添加键值对(K,V)
V remove(Object key);//移除某个键对应的键值对
void putAll(Map<? extends K, ? extends V> m);//添加另一个Map集合
void clear();//清空所有键值对
Set<K> keySet();//获取键的集合
Collection<V> values();//获取值的集合
Set<Map.Entry<K, V>> entrySet();//获取键值对实体的集合
interface Entry<K,V>//Map中的内部接口

HashMap

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)除实现了Map接口外还实现了Cloneable,Serializable,继承了AbstractMap抽象类

此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

特点:

  • 键无序,唯一,类似于Set集合
  • 值有序,可重复,类似于List
  • 底层数据结构是哈希表,保证键唯一

允许键为null,值为null

//   HashMap<String, Student> hm = new HashMap<String, Student>();
//   hm.put("2018050401", new Student("2018050401", "张三", 18, 80.0));
//   hm.put("2018050402", new Student("2018050402", "李四", 18, 80.0));
//   hm.put("2018050403", new Student("2018050403", "李四", 18, 80.0));
//   hm.put("2018050404", new Student("2018050404", "王五", 18, 80.0));
//   hm.put("2018050404", new Student("2018050404", "王五", 18, 80.0));
//
//   // 方式一: 通过键找值
//   Set<String> keys = hm.keySet();
//   for (String key : keys) {
//     Student s = hm.get(key);
//     System.out.println(key + "|" + s.getId() + "|" + s.getName() + "|" + s.getAge() + "|" + s.getScore());
//   }

    HashMap<Student, String> hm = new HashMap<Student, String>();
    hm.put(new Student("2018050401", "张三", 18, 80.0),"2018050401");
    hm.put(new Student("2018050402", "李四", 18, 80.0),"2018050402");
    hm.put(new Student("2018050403", "李四", 18, 80.0), "2018050403");
    hm.put(new Student("2018050404", "王五", 18, 80.0), "2018050404");
    hm.put(new Student("2018050404", "王五", 18, 80.0), "2018050404");

    // 方式二: 通过键值对对象找键找值
    Set<Entry<Student, String>> keyValues = hm.entrySet();
    for (Entry<Student, String> keyValue : keyValues) {
      Student s = keyValue.getKey();
      String value = keyValue.getValue();
      System.out.println(s.getId() + "|" + s.getName() + "|" + s.getAge() + "|" + s.getScore() + "=" + value);
    }

LinkedHashMap

Map 接口的哈希表和链表实现,具有可预知的迭代顺序

特点:

  • 键有序,唯一,
  • 值有序,可重复,类似于List

底层数据结构是哈希表和链表,哈希表保证键唯一,链表保证键有序

    LinkedHashMap<Integer, String> lhm = new LinkedHashMap<Integer, String>();
    lhm.put(01, "张三1");
    lhm.put(02, "张三2");
    lhm.put(03, "张三3");
    lhm.put(04, "张三4");
    lhm.put(05, "张三5");

    Set<Integer> keys = lhm.keySet();
    for (Integer key : keys) {
      System.out.println(key + "|" + lhm.get(key));
    }

TreeMap

基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,

具体取决于使用的构造方法。

特点:

  • 键可排序,唯一,
  • 值有序,可重复,类似于List
  • 底层数据结构是自平衡的二叉树,可排序

排序方式类似于TreeSet,分为自然排序和比较器排序,具体取决于使用的构造方法

    TreeMap<Integer, String> tm = new TreeMap<Integer, String>();
    tm.put(24, "Hello1");
    tm.put(14, "Hello2");
    tm.put(34, "Hello3");
    tm.put(124, "Hello4");
    tm.put(24, "Hello5");
    tm.put(24, "Hello6");
    tm.put(24, "Hello7");
    tm.put(244, "Hello8");
    tm.put(624, "Hello9");
    tm.put(24, "Hello10");
    Set<Integer> keys = tm.keySet();
    for (Integer key : keys) {
      String value = tm.get(key);
      System.out.println(key + "|" + value);
    }

HashTable

此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值

特点:

  • 不允许null键和null值
  • 线程安全,效率低

HashMap和Hashtable的区别:

  • HashMap是不安全的不同步的效率高的 允许null键和null值
  • Hashtable是安全的同步的效率低的 不允许null键和null值

底层都是哈希表结构

Hashtable<String, String> hashtable = new Hashtable<String, String>();
    hashtable.put("刘备", "孙尚香");
    hashtable.put("孙策", "大乔");
    hashtable.put("周瑜", "小乔");
    hashtable.put("吕布", "貂蝉");
    System.out.println(hashtable);
    Enumeration<String> keys = hashtable.keys();
    while (keys.hasMoreElements()) {
      String key = keys.nextElement();
      String value = hashtable.get(key);
      System.out.println(key + "|" + value);
    }

WeakHashMap

以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。
丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。

    WeakHashMap<String,String> whm = new WeakHashMap<>();
    whm.put(new String("hello1"), "world1");
    whm.put(new String("hello2"), "world2");
    whm.put(new String("hello3"), "world3");
    whm.put("hello4", "world3");
    System.out.println(whm);
    System.gc();
    System.runFinalization();
    System.out.println(whm);

键是枚举类型

    EnumMap<Direction, String> em = new EnumMap<>(Direction.class);
    em.put(Direction.UP, "向上移动");
    em.put(Direction.DOWN, "向下移动");
    em.put(Direction.LEFT, "向左移动");
    em.put(Direction.RIGHT, "向右移动");

    Set<Direction> keys = em.keySet();
    for (Direction key : keys) {
      String value = em.get(key);
      System.out.println(key + "|" + value);
    }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java Lambda List转Map代码实例

    在有些开发场景,需要对 List 对象列表进行过滤处理,并将有用的数据存放到Map中. 例如:告警对象,包含告警uuid(alarmUuid) 和 设备uuid(objUuid),需要对 objUuid = -1的告警进行过滤,并将过滤后告警数据的alarmUuid和 objUuid以键值对的形式保存到Map中. 1.告警对象定义如下: /** * Created by Miracle Luna on 2020/3/16 */ public class AlarmInfoResponse { p

  • Java8 HashMap扩容算法实例解析

    这篇文章主要介绍了Java8 HashMap扩容算法实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java8的HashMap扩容过程主要就是集中在resize()方法中 final Node<K,V>[] resize() { // ...省略不重要的 } 其中,当HashMap扩容完毕之后,需要对原有的数据进行转移.因为容量变大了,部分元素的位置因此要变更,因而出现了下面的这个转移过程. 转移过程大致是:依次从旧数组里取值,然后从

  • JAVA使用TreeMap对字符串进行排序

    这篇文章主要介绍了JAVA使用TreeMap对字符串进行排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 题目要求: 给出一个字符串:fjdjskgfhbsjkgjnsrgnaHNGKEURHGASLGNw5y74236720573. 要求: 化成字符串a(字符的个数)b()c()... 区分大小写 只读取字母 直接上代码: import java.util.Map; import java.util.Set; import java.uti

  • Java手写简易版HashMap的使用(存储+查找)

    HashMap的基本结构 package com.liuyuhe; public class Node { int hash; Object key; Object value; Node next; } package com.liuyuhe; public class MyHashMap { Node[] table; //位桶数组 int size; //存放键值对的个数 public MyHashMap() { table=new Node[16]; } } put()方法存储键值对 p

  • java实体对象与Map之间的转换工具类代码实例

    这篇文章主要介绍了java实体对象与Map之间的转换工具类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Map接口中键和值一一映射. 可以通过键来获取值. 给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值. 当访问的值不存在的时候,方法就会抛出一个NoSuchElementException异常. 当对象的类型和Map里元素类型不兼容的时候,就会抛出一个 ClassCastException异常

  • Java for循环Map集合优化实现解析

    这篇文章主要介绍了Java for循环Map集合优化实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在<for循环实战性能优化>中提出了五种提升for循环性能的优化策略,这次我们在其中嵌套循环优化小循环驱动大循环的基础上,借助Map集合高效的查询性能来优化嵌套for循环. 如果小循环和大循环的集合元素数量分别为M和N,则双层For循环的循环次数是M*N,随着M和N的增长,对性能的影响越来越大.因此,本文考虑进一步优化,使得循环次数变为

  • Java HashMap两种简便排序方法解析

    这篇文章主要介绍了Java HashMap两种简便排序方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 HashMap的储存是没有顺序的,而是按照key的HashCode实现. key=手机品牌,value=价格,这里以这个例子实现按名称排序和按价格排序. Map phone=new HashMap(); phone.put("Apple",8899); phone.put("SAMSUNG",7000);

  • Java Map接口及其实现类原理解析

    Map接口 Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value: Map中的键值对以Entry类型的对象实例形式存在: 建(key值)不可重复,value值可以重复,一个value值可以和很多key值形成对应关系,每个建最多只能映射到一个值. Map支持泛型,形式如:Map<K,V> Map中使用put(K key,V value)方法添加 Map接口中定义的常用方法 具体使用在实现类中讨论 int size();//获取Ma

  • Java集合之Map接口的实现类精解

    目录 HashMap类 1.HashMap类概述 2.HashMap的存储结构(底层实现原理) 3.HashMap源码中的重要常量 LinkedHashMap类 TreeMap类 1.TreeMap类概述 2.自然排序 3.定制排序 Hashtable类 Properties类 HashMap类 1.HashMap类概述 HashMap是 Map 接口使用频率最高的实现类,允许使用null键和null值,与HashSet一样,不保证映射的顺序. 所有的key构成的集合是Set:无序的.不可重复的

  • Java日期与时间类原理解析

    这篇文章主要介绍了Java日期与时间类原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 基础知识 日期: 类似于 2018-12-12 时间: 类似于 2018-12-12 12:12:12 时刻: 类似于 2018-12-12 12:12:12 地区: 计算机中的 Locale, 如 zh_CN, en_US 等, 影响着对于日期, 时间, 货币等格式的显示 EpochTime: 从 1970 年 1 月 1 日 UTC+00:00 到

  • Java集合之Map接口与实现类详解

    目录 初识Map Map中常用方法 HashMap LinkedHashMap TreeMap HashMap和TreeMap的比较 Hashtable 集合中元素的遍历 iterator接口中的方法 Enumeration接口中的方法 初识Map Map接口没有从Collection接口继承,Map接口用于维护“键-值”对数据,这个“键-值”对就是Map中的元素,Map提供“键(Key)”到“值(value)”的映射,一个Map中键值必须是唯一的,不能有重复的键,因为Map中的“键-值”对元素

  • Java和Dubbo的SPI机制原理解析

    SPI: 简单理解就是,你一个接口有多种实现,然后在代码运行时候,具体选用那个实现,这时候我们就可以通过一些特定的方式来告诉程序寻用那个实现类,这就是SPI. JAVA的SPI 全称为 Service Provider Interface,是一种服务发现机制.它是约定在 Classpath 下的 META-INF/services/ 目录里创建一个以服务接口命名的文件,然后文件里面记录的是此 jar 包提供的具体实现类的全限定名. 这样当我们引用了某个 jar 包的时候就可以去找这个 jar 包

  • Java多线程并发编程和锁原理解析

    这篇文章主要介绍了Java多线程并发编程和锁原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等方案后,问题得到解决. 加锁方案见下文. 二.乐观锁 & 悲观锁 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁

  • java Map接口子类HashMap遍历与LinkedHashMap详解

    目录 一.概述 二.Map常用子类 三.Map接口中的常用方法 四.Map集合遍历键找值方式 五.Entry键值对对象 六.Map集合遍历键值对方式 七.HashMap存储自定义类型键值 八.LinkedHashMap 九.Map集合练习 十.JDK9对集合添加的优化 一.概述 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射.Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map接口

  • Java 比较接口comparable与comparator区别解析

    这篇文章主要介绍了Java 比较接口comparable与comparator区别解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 package test0; import java.util.Comparator; //限定修饰符为friend不能为public,一个java文件中只能有一个public类 /*** * java程序是从一个public类的main函数开始执行的, *(其实是main线程),就像c程序是从main()函数开

  • Java等待唤醒机制线程通信原理解析

    这篇文章主要介绍了Java等待唤醒机制线程通信原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同.比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消费,那么线程A与线程B之间就存在线程通信问题. 为什么要处理线程间通信: 多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个

  • Java JDBC导致的反序列化攻击原理解析

    这篇文章主要介绍了Java JDBC导致的反序列化攻击原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 背景 上周BlackHat Europe 2019的议题<New Exploit Technique In Java Deserialization Attack>中提到了一个通过注入JDBC URL实现反序列化攻击的场景,简单分析一下. 分析 首先,当java应用使用MySQL Connector/J(官方的JDBC驱动,本文基于其

随机推荐