【Java集合 - Map】HashMap / HashTable / TreeMap 特点、对比、遍历及运用(附三个案例代码)

本文深入探讨了Java中的Map接口及其主要实现类HashMap、HashTable和TreeMap的特点、实现原理及遍历方法。HashMap是非线程安全、高效的,适合多线程环境下使用时同步处理。HashTable线程安全,但效率较低。TreeMap保持元素排序,适用于顺序要求的场景。文章还介绍了字符串处理和正则表达式的基本用法,并提供了三个实际案例。
摘要由CSDN通过智能技术生成

———————————————————————————————————————————————————————

Java中的集合——Map

  • Java 中主要有两种集合:Collection 接口和 Map 接口。
    Java 中的集合

———————————————————————————————————————————————————————

1. Map 的特点

  1. 保存 Key-Value对 形式的元素,访问时只根据每项元素的 key 来访问其 value
  2. 每个 key 都是唯一的,不可重复;但 value 是可以重复的。
  3. 有些映射可以接收 null key 和 null value ,而有的则不行。
  4. Map 不能直接通过 foreach 或迭代器进行遍历,需要把它先转成 Set 集合

2. Map 下的实现类

  • Map 接口下有两个实现类:
  1. HashMap
  2. HashTable
  3. TreeSet

*当元素的顺序很重要时选用 TreeMap;当元素不必以特定的顺序进行存储时,使用 HashMap。
*HashMap 不是同步的,HashTable 是同步的;但 HashTable 不推荐使用,因为 HashMap 提供了所有类似的功能,并且速度更快。
*当需要在多线程环境下使用时,HashMap 也可以转换为同步的。
HashMap 可以通过 Map m = Collections.synchronizedMap(hashMap) 来达到同步的效果。

3. Map 中的方法

  1. put(K key, V value)
    将指定的值与该映射中的指定键相关联(可选操作)。
  2. get(Object key)
    返回到指定键所映射的值,或 null如果此映射包含该键的映射。
  3. clear()
    从该 Map 中删除所有的映射(可选操作)。
  4. containsValue(Object value)
    如果此 Map 将一个或多个键映射到指定的值,则返回 true。
  5. entryset()
    返回此 Map 中包含的映射的 Set 视图。
  6. keySet()
    返回 Map 中 key 的集合。
  7. equals(Object o)
    将指定的对象与此映射进行比较以获得相等性。

import java.util.HashMap;
import java.util.Map;

public class MapDemo {
   
    public static void main(String[] args) {
   
        Map objectHashMap = new HashMap();

        // Map(key,value)
        // 添加集合键值对,如果不指定泛型,键和值都为 Object 类型
        // key 不允许重复
        objectHashMap.put("张三",35); // 实现了自动装箱
        objectHashMap.put("李四",30); // 实现了自动装箱
        objectHashMap.put("王五",33); // 实现了自动装箱
        objectHashMap.put("赵六",31); // 实现了自动装箱

        objectHashMap.put("张三",32);
        // 覆盖原有的 为 "张三" 的 key

        objectHashMap.put(null,null);
        // 允许存在空键,但只能有一个;可以有多个空值

        /*
         * HashMap 的方法与 HashTable 基本一致
         */

        // size()
        // 获取集合的长度
        int size = objectHashMap.size();
        System.out.println("size = " + size);
        // size = 5,因为 key 是不允许重复的,每个 key 都是唯一的


        // get(Object key)
        // 返回指定键所映射的值,如果此映射不包含该键的映射关系,则返回 null
        Object w5 = objectHashMap.get("王五");
        System.out.println("w5 = " + w5);
        // w5 = 33,根据 key 获取 value

        Object z3 = objectHashMap.get("张三");
        System.out.println("z3 = " + z3);
        // z3 = 32

        Object obj = objectHashMap.get(null);
        System.out.println("obj = " + obj);
        // obj = null


        // clear()
        // 清除集合中的所有元素
        /*objectHashMap.clear();*/

        // containsKey(Object key)
        boolean a = objectHashMap.containsKey("张三");
        System.out.println("a = " + a); // true

        // containsValue(Object value)
        boolean b = objectHashMap.containsValue(36);
        System.out.println("b = " + b); // false

        // isEmpty()
        // 如果此 Map 不包含 键值映射关系,则返回 true
        boolean empty = objectHashMap.isEmpty();
        System.out.println("empty = " + empty); // false

        // remove(Object key)
        // 如果存在该键的 键值映射关系,则将其从该 Map 中删除
        objectHashMap.remove("赵六");
        System.out.println("size = " + objectHashMap.size()); // 4
    }
}

———————————————————————————————————————————————————————

HashMap

1. HashMap 的特点

  1. HashMap 是线程不安全的,key 可以为 null
  2. 元素不必以特定的顺序进行存储时,使用 HashMap。
  3. 内部定义了一个 Hash 表。以 Hash 表数据结构实现。
  4. 元素会通过 Hash 转换函数 将元素的 Hash 地址转化成数组中存放的索引。
  5. HashMap 不是同步的,HashTable 是同步的,但 HashTable 不推荐使用,因为 HashMap 提供了所有类似的功能,并且速度更快。
  6. 当需要在多线程环境下使用时,HashMap 也可以转换为同步的。
    HashMap 可以通过 Map m = Collections.synchronizedMap(hashMap) 来达到同步的效果。

2. HashMap 底层实现

  • 内部定义了一个 Hash 表数组。

    *Hash表是数组和链表的结合。

  • 以 Hash 表数据结构实现(初始长度为 16),查找对象时通过 Hash 函数计算其位置,为快速查询而设计。

  • JDK1.8 之前,由数组 + 链表组成。数组是 HashMap 主体,链表主要为了解决哈希冲突而存在的。
    如果定位到数组位置不含链表,对于查找,添加等操作很快,仅需一次寻址。
    如果定位到数组位置含链表,对于添加操作,时间复杂度为 O(1),最新的 Entry(集合当中的 key 对象)会插入链表头部,只需简单改变引用链表即可。
    查找需要遍历链表,通过 key 对象的 equals 方法逐一比对查找。

    *拉链法:
    将链表和数组结合,创建一个链表数组,数组中每一格就是一个链表,若遇到Hah冲突,则将冲突的值加到链表中即可。

  • JDK1.8 版本之后:
    为了解决 Hash 冲突时有了较大的变化,当链表长度大于阈值(默认为 8),链表转换为红黑树,以减小搜索时间。
    TreeMap,TreeSet 以及 JDK1.8 之后的 HashMap 底层都用了红黑树。红黑树为了解决二叉树的缺陷,二叉树在某些情况下会退化成一个线性结构。

  • 元素会通过 Hash 转换函数 将元素的 Hash 地址转化成数组中存放的索引。

3. 通过 entrySet()、keySet() 两种方法遍历 HashMap


import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class EntrySetDemo {
   
    public static void main(String[] args) {
   
        HashMap<String,Integer> map = new HashMap<>();

        map.put("张三",35);
        map.put("李四",30);
        map.put("王五",33);
        map.put("赵六",31);

        // 把 Map 集合转换成 Set 集合,类型是 Map 接口里的内部接口
        Set<Map.Entry<String,Integer>> entries = map.entrySet();
        // 遍历 set 集合,通过 entry.getKey()、entry.getValue()方法分别获取键和值
        for (Map.Entry<String,Integer> entry:entries
             ) {
   
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }

        // 把 Map 集合中所有的 key 转换成一个 Set 集合,
        // 再根据 Map 集合本身的 get(Object key) 方法,就可以获取到 value 值了
        Set<String> stringSet = map.keySet();
        for (String string : stringSet) {
   
            Integer integer = map.get(string);
            System.out.println(string + "=" + integer);
        }

		// 其他组合
		/*Set<Integer> integers = map.keySet();
        Iterator iter = integers.iterator();
        while (iter.hasNext()) {
            Object key = iter.next();
            User user = map.get(key);
            int a = user.getAge();
            String n = user.getName();
            System.out.println(n + " 的年龄是:" + a);
        }*/
    }
}

Extra. 两种方法遍历再解

/**
* Map.Entry<String, Integer>
* Map.Entry 内部类
* <String, Integer> 自定义泛型
*/


        // 第一种遍历方式
        System.out.println("第一种遍历方式:");
        // entrySet()
        // 把 map 转换为 set 集合
        Set<Map.Entry<String
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值