简介

Map用户保存具有映射关系的数据,因此Map集合里保存着两组数,一组值用户保存Map里的key,另一组值用户保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。

接口中定义的方法:

Map中还包括一个内部类Entry,该类封装了一个key-value对。Entry包含如下三个方法:

 

实现类

这里介绍Map接口下的三个重要的集合实现类:
  • HashMap类:HashMap是实现了Map接口的key-value集合,实现了所有map的操作,允许key和value为null,它相当于Hashtable,与之存在的区别是hashMap不是线程安全的,HashMap允许null值。
  • TreeMap类:TreeMap是基于红黑树的实现,也是记录了key-value的映射关系,该映射根据key的自然排序进行排序或者根据构造方法中传入的比较器进行排序,也就是说TreeMap是有序的key-value集合
  • Hashtable类:它是类似与HashMap的key-value的哈希表,不允许key-value为NULL值,另外一点值得注意的是Hashtable是线程安全的

 

对比

虽然HashMap、Hashtable、TreeMap这三个都是Map接口的实现,其内部实现及性能等还是存在区别。

基本

  • HashMap:初始化容量为16,扩容每次为2*oldCap,key和value可以为NULL值
  • Hashtable:初始化容量为11,扩容每次为2*oldCap+1,key和value不可以为NULL值
  • TreeMap:初始化容量为0,内部是红黑树结构,不存在hash冲突的情况,不存在扩容的操作,key和value不可以为NULL值

Key相等判断标准

  • HashMap:两个key通过equals()方法比较返回true,并且两个key的hashCode值也相等
  • Hashtable:两个key通过equals()方法比较返回true,并且两个key的hashCode值也相等
  • TreeMap:两个key通过compareTo()方法返回0

内部原理

  • HashMap:HashMap是散列表实现,内部是数组+链表或者红黑树的结构
  • Hashtable:Hashtable也是散列表实现,内部是数组+链表的结构
  • TreeMap:TreeMap内部是红黑树的结构

线程安全

  • HashMap:不是线程安全的,其实通过Map m = Collections.synchronizeMap(hashMap)的方式也可以使得HashMap变成线程安全的,但是这样做对程序的性能可能是噩梦,在后面会介绍ConcurrentHashMap,建议在多线程的情况下可以使用ConcurrentHashMap替换HashMap.
  • Hashtable:是线程安全的,内部方法使用关键字synchronized修饰
  • TreeMap:不是线程安全的

这里的Hashtable属于同步容器,还有更多的并发容器可以使用,请参考:Java学习笔记—多线程(同步容器和并发容器)

性能分析

按照如下代码对HashMap、Hashtable、TreeMap的性能进行测试

public class HashMapProgress {
//定义用于测试的HashMap
private static HashMap<Integer,Integer> hashMap = new HashMap<>();
//定义用于测试的Hashtable
private static Hashtable<Integer,Integer> hashtable = new Hashtable<>();
//定义用于测试的TreeMap
private static TreeMap<Integer,Integer> treeMap = new TreeMap<>(); /**
* 添加元素的方法
* @param map 对应的map
* @param count 添加个数
*/
public static void addEntry(Map<Integer,Integer> map, int count){
Long startTime = System.currentTimeMillis();
if (count <= 0){
return;
}
for (int i = 0; i < count; i++) {
map.put(i,i);
}
Long endTime = System.currentTimeMillis();
System.out.println("添加(" + count + ")个元素使用时间:" + (endTime - startTime) + "s");
} /**
* 获取元素的方法
* @param map
* @param count
*/
public static void getEntry(Map<Integer,Integer> map, int count){
Long startTime = System.currentTimeMillis();
if (count <= 0){
return;
}
for (int i = 0; i < count; i++) {
map.get(i);
}
Long endTime = System.currentTimeMillis();
System.out.println("获取(" + count + ")个元素使用时间:" + (endTime - startTime) + "s");
} public static void main(String[] args){
System.out.println("-------HashMap测试开始-----");
addEntry(hashMap,1000000);
getEntry(hashMap,1000000);
System.out.println("-------HashMap测试结束-----"); System.out.println("-------Hashtable测试开始-----");
addEntry(hashtable,1000000);
getEntry(hashtable,1000000);
System.out.println("-------Hashtable测试结束-----"); System.out.println("-------TreeMap测试开始-----");
addEntry(treeMap,1000000);
getEntry(treeMap,1000000);
System.out.println("-------TreeMap测试结束-----");
}
}

分别测试了100000,1000000,10000000个数据的情况,测试结果如下所示:

数据量 HashMap Hashtable TreeMap
100000 插入用时:18s 查询用时:9s 插入用时:14s 查询用时:5s 插入用时:33s 查询用时:17s
1000000 插入用时:98s 查询用时:20s 插入用时:625s 查询用时:31s 插入用时:242s 查询用时: 145s
10000000 插入用时:9773s 查询用时:811s 插入用时:15055s 查询用时:3369s 插入用时:22354s 查询用时: 3889s

通过上表可以看出随着数据量的增加,时间变化差异还是很大的,而在单线程的情况下还是尽量使用HashMap,相对于Hashtable、TreeMap性能更好,而针对特定的情况需视情况而论。

 
 
参考:

Java集合—Map的更多相关文章

  1. Java集合Map接口与Map.Entry学习

    Java集合Map接口与Map.Entry学习 Map接口不是Collection接口的继承.Map接口用于维护键/值对(key/value pairs).该接口描述了从不重复的键到值的映射. (1) ...

  2. Java集合——Map接口

    1.定义 Map用于保存存在映射关系<key,value>的数据.其中,key值不能重复(使用equals()方法比较),value值可以重复 2.方法 V  put(key,value) ...

  3. Java集合Map基本方法

    jdk1.7 api中的方法摘要: 参考java集合大全图:https://www.cnblogs.com/xkzhangsanx/p/10889114.html Map为所有Map子类的接口.

  4. java集合——Map

    声明:以下内容都是来自网络总结,将会参考很多,没有声明转载来源. 一.Map接口 1.HashMap HashMap和HashTable的区别:http://blog.csdn.net/shohoku ...

  5. Java集合--Map总结

    转载请注明出处:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3311126 第1部分 Map概括 (01) Map ...

  6. Java集合-----Map详解

          Map与Collection并列存在.用于保存具有映射关系的数据:Key-Value      Map 中的 key 和  value 都可以是任何引用类型的数据      Map 中的 ...

  7. Java集合Map与其子类回顾

    接10月12号昨天的笔记,今天继续回顾集合中的Map集合. 一.集合工具操作类Collections 问题:collection和collections的区别? 1.collection是单列集合的顶 ...

  8. Java集合----Map集合

    Map Map 用于保存具有映射关系的数据,因此 Map 集合里保存着两组值,一组值用于保存 Map 里的 Key,另外一组用于保存 Map 里的 Value Map 中的 key 和 value 都 ...

  9. Java 集合-Map接口和三个子类实现

    2017-10-31 22:05:59 Map 将键映射到值的对象.一个映射不能包含重复的键:每个键最多只能映射到一个值. HashMap是基于散列表实现的,插入.删除和定位元素时间复杂度平均能达到O ...

随机推荐

  1. lnmp服务器的目录信息

    LNMP状态管理命令: LNMP状态管理: /root/lnmp {start|stop|reload|restart|kill|status}Nginx状态管理:/etc/init.d/nginx ...

  2. 关于webRTC中video的使用实践

    此次demo使用chrome49调试测试 前端在操作视频输入,音频输入,输出上一直是比较弱的,或者说很难进行相关的操作,经过我最近的一些研究发现,在PC上实际上是可以实现这一系列的功能的,其实现原理主 ...

  3. 实现现下列哪一种接口的对象,并不需要在web.xml文件内进行额外的设定,Servlet容器就能够回应该对象加入HTTP会话所发生的事件?(选择1项)

    实现现下列哪一种接口的对象,并不需要在web.xml文件内进行额外的设定,Servlet容器就能够回应该对象加入HTTP会话所发生的事件?(选择1项) A.ServletContextListener ...

  4. Unity3d优化总结1

    优化内容 包括: 1.代码方面: 2.函数使用方面: 3.ngui注意方面: 4.数学运算方面: 5.内存方面: 6.垃圾回收方面 等等... 1. 尽量避免每帧处理,可以每隔几帧处理一次 比如:   ...

  5. Web设计的速查卡(转)

    一.排版 1.VisiBone Font Card Download: GIF 2.常用字体表 (HTML) 3.混合字体 (PDF) 二.单元/尺寸 1.Points 和Pixels近似转换表 (H ...

  6. 【NOIP模拟题】行动!行动!(spfa+优化)

    spfa不加优化果断tle最后一个点................... 这题和ch的一题很像,只不过这题简单点,这是一个层次图,即有很多个相同的图,这些相同的图之间又存在着练习.. 然后每一次队列 ...

  7. Android SDK代理server解决国内不能更新下载问题

    读者须知:本篇文章中最靠谱的是第三种方式,近期有读者反映第三种方式也不行了,以下提供一点其它途径的开源镜像网站: 国内高校的开源镜像站 中国科学技术大学(debian.ustc.edu.cn) 上海交 ...

  8. iOS开发之--从URL加载图片

    + (UIImage *) imageFromURLString: (NSString *) urlstring { // This call is synchronous and blocking ...

  9. JS-实时修改在textarea里面的span(实际输入的文字)

    解决办法: 在开发中,多少会遇到一些界面,输入限制字数. 例如: //页面加载完毕 $(function() { //descrip是textarea的id $("#descrip" ...

  10. echarts x轴坐标文字显示不全

    在echarts中应用柱状图或者折线图时,当数据量过多的时候,X轴的坐标就会显示不全(如下图图一),在ECharts图表组件内部有一个机制,用于统计xAxis坐标刻度的个数和图表宽度,从而会自动调整刻 ...