Map日常笔记(HashMap、HashTable、LinkedHashMap、TreeMap)

HashMap:

//类声明  实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {

}
是非线程安全的,只是用于单线程环境下
底层实现:
由数组+单链表/红黑树数据结构存储数据
存储的数据无序,随机存储

HashMap存数据的过程是:

HashMap内部维护了一个存储数据的Entry数组,HashMap采用链表解决冲突,每一个Entry本质上是一个单向链表。
当准备添加一个key-value对时,首先通过hash(key)方法计算hash值,然后通过indexFor(hash,length)
求该key-value对的存储位置,计算方法是先用hash&0x7FFFFFFF后,再对length取模,
这就保证每一个key-value对都能存入HashMap中,当计算出的位置相同时,由于存入位置是一个链表,
则把这个key-value对插入链表头。

HashTable

//类声明  实现了Serializable接口,它支持序列化,实现了Cloneable接口,能被克隆。
public class Hashtable<K,V>
    extends Dictionary<K,V>
    implements Map<K,V>, Cloneable, java.io.Serializable {
Hashtable 中的方法都有Synchronize关键字修饰,所以时线程安全的

HashMap和HashTable的区别

//HashMap是线程不安全的

HashMap<String, Double> boxInfo = new HashMap<>();

//如果想线程安全,则new HashMap的时候这么写:如下

 Map<String, Double> m = Collections.synchronizedMap(new HashMap<>());

参考:HashTable和HashMap的区别详解:https://www.cnblogs.com/williamjie/p/9099141.html

LinkedHashMap

//类声明  继承于HashMap,是基于HashMap和双向链表来实现的
public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
在hashmap的基础上,用双链表实现:
1、双向链表只是为了保证put和get顺序,即存取数据的顺序一致
2、LinkedHashMap有序
3、LinkedHashMap是线程不安全的

LinkedHashMap应用场景:

当我们希望有顺序地去存储key-value时,就需要使用LinkedHashMap了。

TreeMap的用法(主要是排序)

//类声明 默认的排序为升序,需改变排序则实现Comparator接口
public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
{
//TreeMap
1、由红黑树算法实现的
2、是非线程安全的,和hashMap一样

业务需求,需要按时间进行升序展示数据信息:

map结构类似于这样:

private static Map<String, List<CapabilityStatMap>> cacheSlineCapabilityStatMap = new ConcurrentHashMap<>(); 
"data": {
        "aa2994b5-441c-423e-a6ce-1ea717c7b013": [
            {
                "area_id": "",
                "spec_id": "test_spec898",
                "vpl_id": "test_spec898",
                "tem_id": "tem20191211170800-2",
                "day": "2019-12-31T00:00:00",
                "dailyCapability": 8000.3,
                "availableCapability": 0.0,
                "beUsedCapability": 8000.3,
                "sboxesInfoMap": {
                    "01ed2423-6fa3-4d76-a739-801fdfaa9833": {
                        "total": 8000.3,
                        "forget": 6240.3,
                        "used": 1760.0,
                        "ava": 0.0
                    }
                }
            }
    ]
}

自定义比较器

MapKeyComparator
package com.hierway.vslm.common.util;

import java.time.LocalDateTime;
import java.util.Comparator;

/**
 * @Description
 * @Author by mocar小师兄
 * @Date 2019/12/20 11:40
 **/
public class MapKeyComparator implements Comparator<LocalDateTime> {
    @Override
    public int compare(LocalDateTime o1, LocalDateTime o2) {
        //参数o1,小于、等于或者大于o2 ,返回负整数、0或者正整数
        //返回负数则o1在前,正数则o2在前
        if (o1.isBefore(o2)){
            return -1;
        }else if (o1.isAfter(o2)){
            return 1;
        }else {
            return 0;
        }
    }
}

排序的重要逻辑,在new TreeMap的时候,给构造器传一个自己自定义的比较器:

	ArrayList<CapabilityStatMap> capabilityStatMaps = new ArrayList<>();
	List<String> sids = sLineList.stream().map(SLine::getStreamLineId).collect(Collectors.toList());
	for (String sid : sids) {
		List<CapabilityStatMap> capabilityStatMapList = new ArrayList<>();
		if (!CollectionUtils.isEmpty(getCacheSlineCapabilityStatMap())
				&& getCacheSlineCapabilityStatMap().containsKey(sid)) {
			capabilityStatMapList = getCacheSlineCapabilityStatMap().get(sid);
			//合并
			capabilityStatMaps.addAll(capabilityStatMapList);
		} else {
			continue;
		}
	}
	//按查询时间过滤
	List<CapabilityStatMap> capaFilter = capabilityStatMaps.stream().filter(capabilityStatMap -> (capabilityStatMap.getDay().isEqual(startTime) || capabilityStatMap.getDay().isAfter(startTime)) &&
			(capabilityStatMap.getDay().isEqual(endTime) || capabilityStatMap.getDay().isBefore(endTime))).collect(Collectors.toList());
	if (CollectionUtils.isEmpty(capaFilter)) {
		logger.error("在时间:{} -- {} 内,没有查询到产能数据,{}", startTime,endTime,methodStr);
		//return null;
		throw new ApiException(ResultCode.NO_DATA_FOUND);
	}
	//按时间分组
	Map<LocalDateTime, List<CapabilityStatMap>> localDateTimeListMap = capaFilter.stream().collect(Collectors.groupingBy(CapabilityStatMap::getDay));
	//按时间排序   TreeMap
	Map<LocalDateTime, List<CapabilityStatMap>> sortByLocalDateTimeMap = new TreeMap<>(new MapKeyComparator());
	sortByLocalDateTimeMap.putAll(localDateTimeListMap);


红黑树参考: https://blog.csdn.net/cyywxy/article/details/81151104

LinkedHashMap和hashMap和TreeMap的区别: https://www.cnblogs.com/coder-lzh/p/10819627.html

总结:如何选择合适的Map

  • HashMap可实现快速存储和检索,但其缺点是其包含的元素是无序的,这导致它在存在大量迭代的情况下表现不佳。
  • LinkedHashMap保留了HashMap的优势,且其包含的元素是有序的。它在有大量迭代的情况下表现更好。
  • TreeMap能便捷的实现对其内部元素的各种排序,但其一般性能比前两种map差。
  • LinkedHashMap映射减少了HashMap排序中的混乱,且不会导致TreeMap的性能损失。
发布了109 篇原创文章 · 获赞 2 · 访问量 5700

猜你喜欢

转载自blog.csdn.net/Seven71111/article/details/103635864