zoukankan      html  css  js  c++  java
  • Map and HashMap

     

    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值替换。

     

     

  • 相关阅读:
    钱多多软件制作04
    团队项目01应用场景
    HDU 4411 arrest
    HDU 4406 GPA
    HDU 3315 My Brute
    HDU 3667 Transportation
    HDU 2676 Matrix
    欧拉回路三水题 POJ 1041 POJ 2230 POJ 1386
    SPOJ 371 BOXES
    POJ 3422 Kaka's Matrix Travels
  • 原文地址:https://www.cnblogs.com/Mr-Kenson/p/7259829.html
Copyright © 2011-2022 走看看