java_day10:Map 详解-用法,遍历,排序,常用API等

12 篇文章 0 订阅
9 篇文章 0 订阅

Map 详解-用法,遍历,排序,常用API等

1. Map的概要

java.util 中的集合类包含java中某些最常用的类。最常用的集合类型是List和Map
Map提供了一个更通用的元素存储方法。Map集合类用于存储元素对(称作“键”和“值”),其中每一个键映射到一个值。

2. Map的用法

2.1 类型介绍

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

2.2 类型区别

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均允许为空,非同步的。

3.Map基本用法

3.1 Map初始化
Map<String, String> map = new HashMap<String, String>();
3.2 插入元素
map.put("key1", "value1");
3.3 获取元素
map.get("key1")
3.4 移除元素
map.remove("key1");
3.5 清空Map
map.clear();
3.6 四种常用的Map插入和读取性能比较

测试环境:jdk 1.8


测试代码


import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.UUID;

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");
    }
}

测试结果


w/ms插入10次平均(ms)读取10次平均(ms)
测试赋值1w10w100w1w10w100w
HashMap942302246215214
LinkedHashMap401932208315203
TreeMap5226631708901057
Hashtable411912077217232

4. Map 遍历(4种方式)

4.1 初始化数据
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
map.put("key2", "value2");
4.2 增强for循环 keySet()

使用keySet()遍历

for (String key : map.keySet()) {
    System.out.println(key + " :" + map.get(key));
}
4.3 增强for循环 entrySet()

使用entrySet()遍历

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " :" + entry.getValue());
}
4.4 迭代器遍历 keySet()

使用keySet()遍历

Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()) {
    String key = iterator.next();
    System.out.println(key + " :" + map.get(key));
}
4.5 迭代器遍历 entrySet()

使用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());
}

5 Map 排序

HashMap、Hashtable、LinkedHashMap排序


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.1 HashMap四种遍历方式性能测试

比较方式:

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

代码:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.junit.Test;

public class TestMap {
	private final static int SIZE = 500000;
	public static void main(String[] args) {
		
		// 初始化 50w赋值
		Map<Integer, Integer> map = new HashMap<>();
		for (int i = 0; i < SIZE; i++) {
			map.put(i, i);
		}
		/** 
		 * 增强for循环,keySet迭代
		 * 1)21ms
		 * 2)15ms
		 * 3)15ms
		 *  平均值:17ms
		*/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迭代
		 * 1)14ms
		 * 2)17ms
		 * 3)14ms
		 * 平均值:15ms
		 */
		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迭
         * 1)14ms
         * 2)11ms
         * 3)13ms
         * 平均值:12.6ms
         */
        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迭代
         * 1)13ms
         * 2)11ms
         * 3)9ms
         * 平均值:11ms
         */
        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迭代三次压力测试结果

		/** 
		 * 增强for循环,keySet迭代
		 * 1)21ms
		 * 2)15ms
		 * 3)15ms
		 *  平均值:17ms
		 */

增强for循环,entrySet迭代三次压力测试结果

/**
		 * 增强for循环,entrySet迭代
		 * 1)14ms
		 * 2)17ms
		 * 3)14ms
		 * 平均值:15ms
		 */

迭代器,keySet迭代三次测试结果

        /**
         * 迭代器,keySet迭
         * 1)14ms
         * 2)11ms
         * 3)13ms
         * 平均值:12.6ms
         */

迭代器,entrySet迭代三次测试结果**

        /**
         * 迭代器,entrySet迭代
         * 1)13ms
         * 2)11ms
         * 3)9ms
         * 平均值:11ms
         */

总结:

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

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

3)使用entrySet遍历的速度要比keySet要快

6 常用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 中的键-值映射的数目
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值