1.1.1. Map 接口

java提供了一组可以以键值对(key-value)的形式存储数据的数据结构,这种数据结构称为Map。我们可以把Map看成一个多行两列的表格,其中第一列存放key,第二列存放value。

而每一行就相当于一组key-value对,表示一组数据。

Map对存入的元素有一个要求,就是key不能重复,所谓不能重复指的是在Map中不能包含两个equals为true的key。

Map对于key,value的类型没有严格要求,只要是引用类型均可。但是为了保证在使用时不会造成数据混乱,通常我们会使用泛型去约束key与value的类型。

1.1.2. put方法

既然我们知道了Map在保存数据时实际上是存入了两部分信息的 ,key与value。那么我们来看看如何向Map中存入数据。

Map提供了一个方法:

  1. V put(K k,V v)

该方法的作用是将key-value对存入Map中,因为Map中不允许出现重复的key,所以若当次存入的key已经在Map中存在,则是替换value操作,而返回值则为被替换的元素。若此key不存在,那么返回值为null。

1.1.3. get方法

我们学会了如何向Map中存入数据,那么我们再来看看如何获取数据。Map中获取数据的方式是给定Key获取对应的Value。

Map提供了一个方法:

  1. V get(Object key)

该方法的作用就是根据给定的key去查找Map中对应的value并返回,若当前Map中不包含给定的key,那么返回值为null。

1.1.4. containsKey方法

Map中的containsKey方法用于检测当前Map中是否包含给定的key。其方法定义如下:

  1. boolean containsKey(Object key)

若当前Map中包含给定的key(这里检查是否包含是根据key的equals比较结果为依据的。)则返回true。

1.2. HashMap

1.2.1. hash表原理

HashMap是Map的一个常用的子类实现。其实使用散列算法实现的。

HashMap内部维护着一个散列数组(就是一个存放元素的数组),我们称其为散列桶,而当我们向HashMap中存入一组键值对时,HashMap首先获取key这个对象的hashcode()方法的返回值,然后使用该值进行一个散列算法,得出一个数字,这个数字就是这组键值对要存入散列数组中的下标位置。

那么得知了下标位置后,HashMap还会查看散列数组当前位置是否包含该元素。(这里要注意的是,散列数组中每个元素并非是直接存储键值对的,而是存入了一个链表,这个链表中的每个节点才是真实保存这组键值对的。)检查是否包含该元素时根据当前要存入的key在当前散列数组对应位置中的链表里是否已经包含这个key,若不包含则将这组键值对存入链表,否则就替换value。

那么在获取元素时,HashMap同样先根据key的hashcode值进行散列算法,找到它在散列数组中的位置,然后遍历该位置的链表,找到该key所对应的value之后返回。

看到这里可能有个疑问,链表中应该只能存入一个元素,那么HashMap是如何将key-value存入链表的某个节点的呢?实际上,HashMap会将每组键值对封装为一个Entry的实例,然后将该实例存入链表。

1.2.2. hashcode方法

HashMap的存取是依赖于key的hashcode方法的返回值的,而hashcode方法实际上是在Object中定义的。其定义如下:

  1. int hashCode()

重写一个类的hashcode()方法有以下注意事项:

1、若一个类重写了equals方法,那么就应当重写hashcode()方法。

2、若两个对象的equals方法比较为true,那么它们应当具有相同的hashcode值。

3、对于同一个对象而言,在内容没有发生改变的情况下,多次调用hashCode()方法应当总是返回相同的值。

4、对于两个对象equals比较为false的,并不要求其hashcode值一定不同,但是应尽量保证不同,这样可以提高散列表性能。

1.2.3. 装载因子及HashMap优化

在散列表中有一下名词需要了解:

  • Capacity:容量, hash表里bucket(桶)的数量, 也就是散列数组大小.
  • Initial capacity:初始容量, 创建hash表的时 初始bucket的数量, 默认构建容量是16. 也可以使用特定容量.
  • Size : 大小, 当前散列表中存储数据的数量.
  • Load factor:加载因子, 默认值0.75(就是75%), 向散列表增加数据时如果 size/capacity 的值大于Load factor则发生扩容并且重新散列(rehash).

那么当加载因子较小时候散列查找性能会提高, 同时也浪费了散列桶空间容量. 0.75是性能和空间相对平衡结果. 在创建散列表时候指定合理容量, 从而可以减少rehash提高性能。

1.3. 有序Map

1.3.1. LinkedHashMap实现有序的Map

Map 接口的哈希表和链表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,LinkedHashMap维护着一个双向循环链表。此链表定义了迭代顺序,该迭代顺序通常就是将存放元素的顺序。

需要注意的是,如果在Map中重新存入以有的key,那么key的位置会不会发生改变,只是将value值替换。

最新文章

  1. UITextField的代理方法:textField:shouldChangeCharactersInRange:replacementString
  2. .net 实现Office文件预览,word文件在线预览、excel文件在线预览、ppt文件在线预览
  3. 《BI那点儿事》数据流转换——字符映射表
  4. uestc oj 1218 Pick The Sticks (01背包变形)
  5. canvas图形处理和进阶用法
  6. MQTT——入门介绍
  7. Regular expressions in lexing and parsing(翻译)
  8. zabbix web监控模板
  9. 基于Spring注解搭建SpringMVC项目
  10. matlab的Deep Learning的toolbox 中的SAE算法
  11. Ubantu linux中使用PyCharm之---破解PyCharm,实现永久免费试用
  12. Javaweb学习笔记——(九)——————Servlet的进入,及ServletConfig、GenericServlet、HttpServlet、ServletContext、获取类路径资源
  13. MyBatis 源码分析系列文章导读
  14. python第十七天---时间模块、random模块
  15. Python3里查看某一元素的源码(检查元素定位是否准确)
  16. Python2.7-bz2
  17. Alpha冲刺——day10
  18. VS2017企业版本(安装包+key)+ .NET Reflector 9.0
  19. sencha touch list + carousel scrollable(与其他控件共用滚动条)
  20. 开发中经典sql总结

热门文章

  1. 【t079】火星上的加法运算
  2. linux下C调用lua的第一个程序
  3. TP5单例模式操作Model
  4. PHP开源框架Laravel的安装与配置
  5. [转]分布式session的几种实现方式
  6. 安装vue-cli和安装nuxt
  7. Java8 API学习2 - java.lang.CharSequence, java.lang.String
  8. Linux 内核PC/104 和 PC/104+
  9. Comb CodeForces - 46E (动态规划)
  10. Vue仿网易云PC端的网页