Java map集合深入学习

Java map集合深入学习  概要:java.util中的集合类包含Java中某些最常用的类。最常用的集合类是List和Map。Map提供了一个更通用的元素存储方法。Map集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。本文主要介绍javamap的初始化、用法、map的四种常用的遍历方式、map的排序以及常用api。目录1Map用法类型介绍类型区别…

大家好,又见面了,我是你们的朋友全栈君。

 

 

概要:

java.util 中的集合类包含 Java 中某些最常用的类。最常用的集合类是 List 和 Map。

Map 提供了一个更通用的元素存储方法。Map 集合类用于存储元素对(称作“键”和“值”),其中每个键映射到一个值。

本文主要介绍java map的初始化、用法、map的四种常用的遍历方式、map的排序以及常用api。

目录

1Map用法

类型介绍

类型区别

Map 初始化

插入元素

获取元素

移除元素

清空map

2四种常用Map插入与读取性能比较

测试环境

测试结果

测试代码

3Map 遍历

初始化数据

增强for循环遍历

迭代器遍历

HashMap四种便利方式性能比较

4Map 排序

HashMap、Hashtable、LinkedHashMap排序

TreeMap排序

按value排序(通用)

5常用API


1Map用法

类型介绍

Java 自带了各种 Map 类。这些 Map 类可归为三种类型:

1. 通用Map,用于在应用程序中管理映射,通常在 java.util 程序包中实现

HashMap、Hashtable、Properties、LinkedHashMap、IdentityHashMap、TreeMap、WeakHashMap、ConcurrentHashMap

2. 专用Map,通常我们不必亲自创建此类Map,而是通过某些其他类对其进行访问

java.util.jar.Attributes、javax.print.attribute.standard.PrinterStateReasons、java.security.Provider、java.awt.RenderingHints、javax.swing.UIDefaults

3. 一个用于帮助我们实现自己的Map类的抽象类

AbstractMap

类型区别

HashMap

最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为 Null。非同步的。

TreeMap

能够把它保存的记录根据键(key)排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。TreeMap不允许key的值为null。非同步的。 
Hashtable

与 HashMap类似,不同的是:key和value的值均不允许为null;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。 
LinkedHashMap

保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。key和value均允许为空,非同步的。 

Map 初始化

Map<String, String> map = new HashMap<String, String>();

插入元素

map.put("key1", "value1");

获取元素

	map.get("key1")

移除元素

map.remove("key1");

清空map

map.clear();

2四种常用Map插入与读取性能比较

测试环境

jdk1.7.0_80

测试结果

  插入10次平均(ms) 读取10次平均(ms)
  1W 10W 100W 1W 10W 100W
HashMap 56 261 3030 2 21 220
LinkedHashMap 25 229 3069 2 20 216
TreeMap 29 295 4117 5 103 1446
Hashtable 24 234 3275 2 22 259

测试代码

 

public class Test {

    static int hashMapW = 0;

    static int hashMapR = 0;

    static int linkMapW = 0;

    static int linkMapR = 0;

    static int treeMapW = 0;

    static int treeMapR = 0;

    static int hashTableW = 0;

    static int hashTableR = 0;



    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {

            Test test = new Test();

            test.test(100 * 10000);

            System.out.println();

        }



        System.out.println("hashMapW = " + hashMapW / 10);

        System.out.println("hashMapR = " + hashMapR / 10);

        System.out.println("linkMapW = " + linkMapW / 10);

        System.out.println("linkMapR = " + linkMapR / 10);

        System.out.println("treeMapW = " + treeMapW / 10);

        System.out.println("treeMapR = " + treeMapR / 10);

        System.out.println("hashTableW = " + hashTableW / 10);

        System.out.println("hashTableR = " + hashTableR / 10);

    }



    public void test(int size) {

        int index;

        Random random = new Random();

        String[] key = new String[size];



        // HashMap 插入

        Map<String, String> map = new HashMap<String, String>();

        long start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            key[i] = UUID.randomUUID().toString();

            map.put(key[i], UUID.randomUUID().toString());

        }

        long end = System.currentTimeMillis();

        hashMapW += (end - start);

        System.out.println("HashMap插入耗时 = " + (end - start) + " ms");



        // HashMap 读取

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            index = random.nextInt(size);

            map.get(key[index]);

        }

        end = System.currentTimeMillis();

        hashMapR += (end - start);

        System.out.println("HashMap读取耗时 = " + (end - start) + " ms");



        // LinkedHashMap 插入

        map = new LinkedHashMap<String, String>();

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            key[i] = UUID.randomUUID().toString();

            map.put(key[i], UUID.randomUUID().toString());

        }

        end = System.currentTimeMillis();

        linkMapW += (end - start);

        System.out.println("LinkedHashMap插入耗时 = " + (end - start) + " ms");



        // LinkedHashMap 读取

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            index = random.nextInt(size);

            map.get(key[index]);

        }

        end = System.currentTimeMillis();

        linkMapR += (end - start);

        System.out.println("LinkedHashMap读取耗时 = " + (end - start) + " ms");



        // TreeMap 插入

        key = new String[size];

        map = new TreeMap<String, String>();

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            key[i] = UUID.randomUUID().toString();

            map.put(key[i], UUID.randomUUID().toString());

        }

        end = System.currentTimeMillis();

        treeMapW += (end - start);

        System.out.println("TreeMap插入耗时 = " + (end - start) + " ms");



        // TreeMap 读取

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            index = random.nextInt(size);

            map.get(key[index]);

        }

        end = System.currentTimeMillis();

        treeMapR += (end - start);

        System.out.println("TreeMap读取耗时 = " + (end - start) + " ms");



        // Hashtable 插入

        key = new String[size];

        map = new Hashtable<String, String>();

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            key[i] = UUID.randomUUID().toString();

            map.put(key[i], UUID.randomUUID().toString());

        }

        end = System.currentTimeMillis();

        hashTableW += (end - start);

        System.out.println("Hashtable插入耗时 = " + (end - start) + " ms");



        // Hashtable 读取

        start = System.currentTimeMillis();

        for (int i = 0; i < size; i++) {

            index = random.nextInt(size);

            map.get(key[index]);

        }

        end = System.currentTimeMillis();

        hashTableR += (end - start);

        System.out.println("Hashtable读取耗时 = " + (end - start) + " ms");

    }

}

3Map 遍历

初始化数据

 

Map<String, String> map = new HashMap<String, String>();

map.put("key1", "value1");

map.put("key2", "value2");

增强for循环遍历

使用keySet()遍历

 

for (String key : map.keySet()) {

    System.out.println(key + " :" + map.get(key));

}

使用entrySet()遍历

 

for (Map.Entry<String, String> entry : map.entrySet()) {

    System.out.println(entry.getKey() + " :" + entry.getValue());

}

迭代器遍历

使用keySet()遍历

 

Iterator<String> iterator = map.keySet().iterator();

while (iterator.hasNext()) {

    String key = iterator.next();

    System.out.println(key + " :" + map.get(key));

}

使用entrySet()遍历

Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();

while (iterator.hasNext()) {

    Map.Entry<String, String> entry = iterator.next();

    System.out.println(entry.getKey() + " :" + entry.getValue());

}

HashMap四种便利方式性能比较

比较方式

分别对四种遍历方式进行10W次迭代,比较用时。

代码

package net.xsoftlab.baike;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;
import java.util.Map.Entry;

public class TestMap {

    public static void main(String[] args) {

        // 初始化,10W次赋值

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();

        for (int i = 0; i < 100000; i++)

            map.put(i, i);

        /** 增强for循环,keySet迭代 */

        long start = System.currentTimeMillis();

        for (Integer key : map.keySet()) {

            map.get(key);

        }

        long end = System.currentTimeMillis();

        System.out.println("增强for循环,keySet迭代 -> " + (end - start) + " ms");

        /** 增强for循环,entrySet迭代 */

        start = System.currentTimeMillis();

        for (Entry<Integer, Integer> entry : map.entrySet()) {

            entry.getKey();

            entry.getValue();

        }

        end = System.currentTimeMillis();

        System.out.println("增强for循环,entrySet迭代 -> " + (end - start) + " ms");

        /** 迭代器,keySet迭代 */

        start = System.currentTimeMillis();

        Iterator<Integer> iterator = map.keySet().iterator();

        Integer key;

        while (iterator.hasNext()) {

            key = iterator.next();

            map.get(key);

        }

        end = System.currentTimeMillis();

        System.out.println("迭代器,keySet迭代 -> " + (end - start) + " ms");

        /** 迭代器,entrySet迭代 */

        start = System.currentTimeMillis();

        Iterator<Map.Entry<Integer, Integer>> iterator1 = map.entrySet().iterator();

        Map.Entry<Integer, Integer> entry;

        while (iterator1.hasNext()) {

            entry = iterator1.next();

            entry.getKey();

            entry.getValue();

        }

        end = System.currentTimeMillis();

        System.out.println("迭代器,entrySet迭代 -> " + (end - start) + " ms");

    }

}

运行三次,比较结果

第一次

 

增强for循环,keySet迭代 -> 37 ms

增强for循环,entrySet迭代 -> 19 ms

迭代器,keySet迭代 -> 14 ms

迭代器,entrySet迭代 -> 9 ms

第二次

 

增强for循环,keySet迭代 -> 29 ms

增强for循环,entrySet迭代 -> 22 ms

迭代器,keySet迭代 -> 19 ms

迭代器,entrySet迭代 -> 12 ms

第三次

 

增强for循环,keySet迭代 -> 27 ms

增强for循环,entrySet迭代 -> 19 ms

迭代器,keySet迭代 -> 18 ms

迭代器,entrySet迭代 -> 10 ms

平均值

 

增强for循环,keySet迭代 -> 31 ms

增强for循环,entrySet迭代 -> 20 ms

迭代器,keySet迭代 -> 17 ms

迭代器,entrySet迭代 -> 10.33 ms

总结

  1. 增强for循环使用方便,但性能较差,不适合处理超大量级的数据。

  2. 迭代器的遍历速度要比增强for循环快很多,是增强for循环的2倍左右。

  3. 使用entrySet遍历的速度要比keySet快很多,是keySet的1.5倍左右。

4Map 排序

HashMap、Hashtable、LinkedHashMap排序

注:

TreeMap也可以使用此方法进行排序,但是更推荐下面的方法。

Map<String, String> map = new HashMap<String, String>();

map.put("a", "c");
map.put("b", "b");
map.put("c", "a");

// 通过ArrayList构造函数把map.entrySet()转换成list

List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(map.entrySet());

// 通过比较器实现比较排序

Collections.sort(list, new Comparator<Map.Entry<String, String>>() {

    public int compare(Map.Entry<String, String> mapping1, Map.Entry<String, String> mapping2) {

        return mapping1.getKey().compareTo(mapping2.getKey());

    }

});

for (Map.Entry<String, String> mapping : list) {

    System.out.println(mapping.getKey() + " :" + mapping.getValue());

}

TreeMap排序

TreeMap默认按key进行升序排序,如果想改变默认的顺序,可以使用比较器:

 

Map<String, String> map = new TreeMap<String, String>(new Comparator<String>() {

    public int compare(String obj1, String obj2) {

        return obj2.compareTo(obj1);// 降序排序

    }
});

map.put("a", "c");

map.put("b", "b");

map.put("c", "a");

for (String key : map.keySet()) {

    System.out.println(key + " :" + map.get(key));

}

按value排序(通用)

 

Map<String, String> map = new TreeMap<String, String>();

        map.put("a", "c");

        map.put("b", "b");

        map.put("c", "a");


        // 通过ArrayList构造函数把map.entrySet()转换成list

        List<Map.Entry<String, String>> list = new ArrayList<Map.Entry<String, String>>(map.entrySet());

        // 通过比较器实现比较排序

        Collections.sort(list, new Comparator<Map.Entry<String, String>>() {

            public int compare(Map.Entry<String, String> mapping1, Map.Entry<String, String> mapping2) {

                return mapping1.getValue().compareTo(mapping2.getValue());

            }

        });


        for (String key : map.keySet()) {

            System.out.println(key + " :" + map.get(key));

        }

5常用API

 

clear() 从 Map 中删除所有映射
remove(Object key) 从 Map 中删除键和关联的值
put(Object key, Object value) 将指定值与指定键相关联
putAll(Map t) 将指定 Map 中的所有映射复制到此 map
entrySet() 返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
keySet() 返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)
values() 返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)
get(Object key) 返回与指定键关联的值
containsKey(Object key) 如果 Map 包含指定键的映射,则返回 true
containsValue(Object value) 如果此 Map 将一个或多个键映射到指定值,则返回 true
isEmpty() 如果 Map 不包含键-值映射,则返回 true
size() 返回 Map 中的键-值映射的数目

 转自:Java初级码农 

出处https://www.cnblogs.com/lzq198754/p/5780165.html

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139408.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • idea2021 激活码(最新序列号破解)

    idea2021 激活码(最新序列号破解),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月18日
    123
  • 弹性网络回归模型_数据模型剪枝

    弹性网络回归模型_数据模型剪枝本文首发于PandaCV公众号。导语:模型剪枝算法核心在于找到“不重要”的参数并且实现裁剪。为寻找到较优的剪枝策略,我们往往需要尝试多种剪枝策略和剪枝策略性能评估。通常剪枝策略评估方法是将剪枝后的模型训练到收敛或者训练规定好数量epoch后进行性能比较。不管是人工调试剪枝策略还是自动搜索剪枝策略,都需要多次评估剪枝策略。剪枝策略的评估效率一定程度上影响了整体压缩效率。因此,本文提出了一种能够快速衡量剪枝后模型性能的方法,经实验能够对MobilenetV1减少50%的FLOPs情况下,仍能保证在Image

    2022年8月16日
    16
  • 序列化和反序列化的底层实现原理是什么?

    序列化和反序列化的底层实现原理是什么?序列化和反序列化作为Java里一个较为基础的知识点,大家心里也有那么几句要说的,但我相信很多小伙伴掌握的也就是那么几句而已,如果再深究问一下Java如何实现序列化和反序列化的,就可能不知所措了!遥记当年也被问了这一个问题,自信满满的说了一大堆,什么是序列化、什么是反序列化、什么场景的时候才会用到等,然后面试官说:那你能说一下序列化和反序列化底层是如何实现的吗?一脸懵逼,然后回家等通知!一、…

    2022年6月15日
    27
  • 数据挖掘-层次聚类

    数据挖掘-层次聚类微信搜索 二十同学 公众号 欢迎关注一条不一样的成长之路层次聚类 hierarchical 算法极为简单 有 N 多节点 最开始认为每个节点为一类 然后找到距离最近的节点 两两合并 合并后的两个节点的平均值作为新的节点 继续两两合并的过程 直到最后都合并成一类 下图表明了聚类的过程 距离最近的节点合并 第一步中 如果有两对节点距离一样 那就同时合并 层次聚类过程如果用数据挖掘工具来做 如 SPSS 一般会生成一个树形图 那么我们可以根据分析问题的具体情况 选

    2026年1月15日
    1
  • Git 切换分支命令

    Git 切换分支命令从Github上clone下来的项目都是主分支branch,为了开发的安全性,如何切换到其它分支呢?gitbranch查看本地分支*表示当前所处的分支,如下图所示:gitbranch-a查看项目所有分支:gitcheckout-b切换分支,例如我切换到stardard-base-4.x-dev:gitcheckout-bstandard-base-4.x-devorigin/standard-base-4.x-dev第二次切换直接填入分支名称即可。

    2022年6月20日
    81
  • 安全 | 几种wifi密码破解的思路

    从一个攻击者的视角,多种方案,讲述破解一台路由器进而控制对方网络的过程,以此提醒广大用户,提高安全意识,做好安全措施。

    2022年4月13日
    170

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号