转:https://www.cnblogs.com/lzq198754/p/5780165.html

Java map 详解 - 用法、遍历、排序、常用API等

概要:

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

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

本文主要介绍java map的初始化、用法、map的四种常用的遍历方式、map的排序以及常用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 初始化

Java | 复制
1
Map<String, String> map = new HashMap<String, String>();

插入元素

Java | 复制
1
map.put("key1""value1");

获取元素

Java | 复制
1
map.get("key1")

移除元素

Java | 复制
1
map.remove("key1");

清空map

Java | 复制
1
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

测试代码

Java | 复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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 遍历

初始化数据

Java | 复制
1
2
3
Map<String, String> map = new HashMap<String, String>();
map.put("key1""value1");
map.put("key2""value2");

增强for循环遍历

使用keySet()遍历

Java | 复制
1
2
3
for (String key : map.keySet()) {
    System.out.println(key + " :" + map.get(key));
}

使用entrySet()遍历

Java | 复制
1
2
3
for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " :" + entry.getValue());
}

迭代器遍历

使用keySet()遍历

Java | 复制
1
2
3
4
5
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
    String key = iterator.next();
    System.out.println(key + " :" + map.get(key));
}

使用entrySet()遍历

Java | 复制
1
2
3
4
5
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次迭代,比较用时。

代码

Java | 复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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");
    }
}

运行三次,比较结果

第一次

Text | 复制
1
2
3
4
增强for循环,keySet迭代 -> 37 ms
增强for循环,entrySet迭代 -> 19 ms
迭代器,keySet迭代 -> 14 ms
迭代器,entrySet迭代 -> 9 ms

第二次

Text | 复制
1
2
3
4
增强for循环,keySet迭代 -> 29 ms
增强for循环,entrySet迭代 -> 22 ms
迭代器,keySet迭代 -> 19 ms
迭代器,entrySet迭代 -> 12 ms

第三次

Text | 复制
1
2
3
4
增强for循环,keySet迭代 -> 27 ms
增强for循环,entrySet迭代 -> 19 ms
迭代器,keySet迭代 -> 18 ms
迭代器,entrySet迭代 -> 10 ms

平均值

Text | 复制
1
2
3
4
增强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也可以使用此方法进行排序,但是更推荐下面的方法。

Java | 复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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进行升序排序,如果想改变默认的顺序,可以使用比较器:

Java | 复制
1
2
3
4
5
6
7
8
9
10
11
12
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排序(通用)

Java | 复制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 中的键-值映射的数目

Map使用方法的更多相关文章

  1. Map.putAll方法——追加另一个Map对象到当前Map集合

    转: Map.putAll方法——追加另一个Map对象到当前Map集合(转) 该方法用来追加另一个Map对象到当前Map集合对象,它会把另一个Map集合对象中的所有内容添加到当前Map集合对象. 语法 ...

  2. Java之map使用方法

    package basic; import java.util.HashMap; import java.util.Map; //map使用方法 public class MapDemo { publ ...

  3. 百度地图bd map使用方法

    一个经验:(当项目中的方法, 很多的时候, 相互调用的时候) 可以在script中, 先定义, 注意是定义, 一个"入口"函数, function initMap(), 然后, 让 ...

  4. MAP使用方法集合

    一.整理: 看到array,就要想到角标. 看到link,就要想到first,last. 看到hash,就要想到hashCode,equals. 看到tree,就要想到两个接口.Comparable, ...

  5. Java中将对象转换为Map的方法

    将对象转换为Map的方法,代码如下: /** * 将对象转成TreeMap,属性名为key,属性值为value * @param object 对象 * @return * @throws Illeg ...

  6. 复制Map对象:Map.putAll方法

    复制Map对象:Map.putAll方法 Map.putAll方法可以追加另一个Map对象到当前Map集合 package xmu.sxl; import java.util.HashMap; imp ...

  7. java 遍历map的方法

    package com.jackey.topic; import java.util.ArrayList;import java.util.HashMap;import java.util.Itera ...

  8. 三种将list转换为map的方法(传统方法、jdk8 Stream流、guava)

    三种将list转换为map的方法 - jackyrong - ITeye博客:http://jackyrong.iteye.com/blog/2158009

  9. JS数组中every(),filter(),forEach(),map(),some()方法学习笔记!

    ES5中定义了五种数组的迭代方法:every(),filter(),forEach(),map(),some(). 每个方法都接受两个参数:要在每一项运行的函数(必选)和运行该函数的作用域的对象-影响 ...

  10. map遍历方法

    java中遍历MAP的几种方法 Java代码 Map<String,String> map=new HashMap<String,String>();    map.put(& ...

随机推荐

  1. [转]OLAP的12条准则

    OLAP的12条准则 Multidimensional conceptual view OLAP模型必须提供多维概念视图 User-analysts would view an enterprise ...

  2. (微信小程序)二 : 创建一个页面。

    首先先看一下pages的目录结构吧. 我创建了一个topics页面.3个文件全创建好了之后 我往topics.js添加数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ...

  3. C#基础:传入URL,获得Http Post

    #region 传入url,获得Http Post public string HttpGet(string url) { string result = string.Empty; try { va ...

  4. [android] 练习样式主题自定义activity切换动画

    主要练习了自定义样式和主题,继承android系统默认的样式并修改,练习xml定义淡入淡出动画 anim/fade_in.xml <?xml version="1.0" en ...

  5. Servlet开发(一)

    1. Servlet简介 Servlet是服务器端程序,主要用来交互式地浏览和修改数据,生成动态web内容.Servlet是SUN公司提供的一个接口,广义的Servlet可以指任何实现了Servlet ...

  6. 廖雪峰JavaScript练习题2

    请把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字.输入:['adam', 'LISA', 'barT'],输出:['Adam', 'Lisa', 'Bart'] 肯定有更简单的方法, ...

  7. csharp:Google TTS API text to speech

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  8. 简单理解C#中的抽象工厂模式是什么概念!

    抽象工厂模式向客户端提供一个接口,使得客户端在不必指定具体类型的情况下,创建多个产品族中的对象.本文采取的仍然是接着以前的那个快餐店的例子.现在,快餐店经常良好,逐渐发展壮大,为了适合不同地方人的饮食 ...

  9. CentOS 7运维管理笔记(6)----Apache 基于 IP 的虚拟主机配置

    Apache 配置虚拟主机支持3种方式:基于IP的虚拟主机配置,基于端口的虚拟主机配置,基于域名的虚拟主机配置.本篇随笔记录自己基于IP的虚拟主机配置. 如果同一台服务器有多个IP,可以使用基于IP的 ...

  10. 转:hive-列转行和行转列

    1. 假设我们在hive中有两张表,其中一张表是存用户基本信息,另一张表是存用户的地址信息等,表数据假设如下: user_basic_info: id name 1 a 2 b 3 c 4 d use ...