【Java集合】Map

前面总结的List,Set,Queue都是Collection下的实现类,本篇博客总结的是与Collection并列的集合,Map.

Map是key-value键值对,key不允许重复,value可以。

Map的常用实现类主要有:HashMap,TreeMap,LinkedHashMap,HashTable.

一. HashMap和HashTable

HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。

HashMap和Hashtable都是Map接口的经典实现类,它们之间的关系完全类似于之前介绍的ArrayList和Vector的关系。

(一)区别:

1.Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能好一些;但如果有多个线程访问同一个Map对象时,是盗用Hashtable实现类会更好。

2.Hashtable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointerException异常;但是HashMap可以使用null作为key或value。

(二)判断key与value相等的标准:

  1. key判断相等的标准:类似于HashSet,HashMap与Hashtable判断两个key相等的标准是:两个key通过equals()方法比较返回true,两个key的hashCode值也相等,则认为两个key是相等的。

  2. value判断相等的标准:只要两个对象通过equals()方法比较返回true即可。

(三)HashMap的构造函数:

// 默认构造函数。
HashMap()

// 指定“容量大小”的构造函数
HashMap(int capacity)

// 指定“容量大小”和“加载因子”的构造函数
HashMap(int capacity, float loadFactor)

// 包含“子Map”的构造函数
HashMap(Map<? extends K, ? extends V> map)

构造函数中,两个重要的元素为容量大小和加载因子。

容量(capacity)是哈希表的容量,初始容量是哈希表在创建时的容量(即DEFAULT_INITIAL_CAPACITY = 1 6)。
加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 resize操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子是 0.75(即DEFAULT_LOAD_FACTOR = 0.75f), 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 resize操作次数。如果容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

(四)HashMap的遍历方式(此处省略构造HashMap代码):

1.遍历HashMap的键值对

        //通过 Map.entrySet() 得到 Map 的 Entry集合,然后遍历
        Set<Map.Entry<String, Object>> entrys = hashMap.entrySet();
        for(Map.Entry<String, Object> entry: entrys){
            String key = entry.getKey();
            Object value2 = entry.getValue();
            System.out.println(key+"="+value2);
        }

2.遍历HashMap的键

       //通过 map.keySet() 得到 Map 的key 的集合,然后 通过 get(key) 得到 Value
        Set<String> set = hashMap.keySet();
        for(String str : set){
            Object obj = hashMap.get(str);
            //System.out.println(str+"="+obj);
        }

3.遍历HashMap的值

        //通过 map.values() 方法得到 Map 中的 value 集合
        Collection<Object> value = hashMap.values();
        for(Object obj : value){
            //System.out.println(obj);
        }

二. LinkedHashMap

HashSet有一个LinkedHashSet子类,HashMap也有一个LinkedHashMap子类;LinkedHashMap使用双向链表来维护key-value对的次序。

LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能;但是因为它以链表来维护内部顺序,所以在迭代访问Map里的全部元素时有较好的性能。迭代输出LinkedHashMap的元素时,将会按照添加key-value对的顺序输出。

本质上来讲,LinkedHashMap=散列表+循环双向链表

三. TreeMap

TreeMap是SortedMap接口的实现类。TreeMap 是一个有序的key-value集合,它是通过红黑树实现的,每个key-value对即作为红黑树的一个节点。

TreeMap排序方式和TreeSet一样,包括自然排序和定制排序。

TreeMap的本质:红黑树。关于红黑树的介绍,曾看到过一篇文章:

https://www.sohu.com/a/201923614_466939 《漫画算法:什么是红黑树》

四. 适用场景

一般的应用场景,尽可能多考虑使用HashMap,因为其为快速查询设计的。

如果需要特定的排序时,考虑使用TreeMap。

如果仅仅需要插入的顺序时,考虑使用LinkedHashMap

五. Map在项目中的应用
Map在项目中也用的挺多,在定义方法的返回类型时,一般会根据返回对象确定是返回实体还是使用Map构造结果集。在项目中,也经常会使用List’<’Map’<’String,Object>>作为结果集返回。下面给出一个简单的代码应用,查询结果集为List’<’Map’<’String,Object>>,最后返回的结果是按照某一key值进行排序的:

List<Map<String, Object>> resultMapList = companyService.queryNearlyCompany(position, area_id, distance, platformId);
        ReturnMsg msg = ReturnMsg.getSuccessMsg();
        if (resultMapList != null && !resultMapList.isEmpty()) {
            logger.info("排序前" + resultMapList);
            CaluateDistanceUtil.listSort(resultMapList);
            logger.info("排序后" + resultMapList);
            msg.getData().put("companies", resultMapList);
        } else {
            msg.getData().put("companies", Collections.EMPTY_LIST);
        }
//将查询到的集合按照距离从近到远进行排序
public static void listSort(List<Map<String, Object>> resultList) {
        Collections.sort(resultList, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {

                double distance1 = Double.parseDouble(MapUtils.getString(o1, "distance"));
                double distance2 = Double.parseDouble(MapUtils.getString(o2, "distance"));
                double p = distance1 - distance2;
                if (p > 0) {
                    return 1;
                } else if (p == 0) {
                    return 0;
                } else {
                    return -1;
                }
            }
        });
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值