• Map
  • 提供的方法
  • HaspMap
  • 存储结构
  • 插入及扩容
  • HashMap和Hashtable
  • HashMap的迭代方法
  • 判等原则
  • LinkedHashMap


Map


Map系:

java map比较value java判断map的value是否重复_System

每一个Map元素包括两个值,一个是key另一个是value,二者存在映射关系,也就是可以通过key索引得到唯一对应的value。所以Map中key不允许重复,key的相等与否通过equals()方法确定,key和value都是任何引用类型的数据。

Map中的key在一起就组成了一个Set集合(无序、不重复),并且Map提供了keySet()方法,用于返回所有key组成的Set集合。

Map和Set有很多相似的地方,如果把Map中存储的Key-Value对称一个变量,并且value是key的附庸,key在哪里valuse就在哪里的话,Map和Set就没有什么区别了。而如果把所有的value放在一起来看,Map又像是一个List(可重复,key看作索引)。



提供的方法

方法

功能

void clear()

清空Map

booelan containsKey(Object key)

booelan containsValue(Object key)

Set entrySet()

返回key-value对组成的Set集合;

Object get(Object key)

获取key对应的value,不存在则返回null

boolean isEmpty()

Set keySet()

返回所有key组成的Set集合

Object put(Object key, Object value)

添加一对值,如果已有key相同的,覆盖

void putAll(Map m)

将m中的全部kv对复制到本map中

Object remove(Objecct key)

删除kv对,返回value,key不存在返回null

int size()

Collection values()

返回该map中所有value组成的Collection

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

getKey(), getValue() 以及setValue()。



HaspMap

存储结构

HashMap内部数据结构:数组+单链表。

数组为了索引访问,单链表为了HashCode相等但是equals返回false的问题。(和HashSet很像)。

table[0] 指定用于存储key = null的键值对。

数组的容量一定是2n,即使在创建时传入的参数不是2nHashMap也会将其向上转换。
如下图:(图源

java map比较value java判断map的value是否重复_System_02

插入及扩容

创建HashMap的默认大小是16。在向HashMap添加kv对时,和HashSet一样,hashCode决定下标。

数组中的每一个位置被称作一个,桶中除了存放key,value外,还有自己的哈希值以及一个链表Entry。同一个链表中存放哈希值散列桶取模运算(就是hashCode%capacity)结果相同的 Entry。如果HashCode相同,equals返回false时,新来的元素会被放置到对应桶中并插在原元素之前,也就是说,这里的链表采用的是“头插法”。

HashMap的扩容有些特殊,一般容器是装满了才进行扩容,但HashMap不是。它有一个LOAD_FACTOR就是装载因子(小于1)来限制HashMap的装载量(maxLoad = capacity * LOAD_FACTOR),也就是说它里面的元素个数是达不到最大容量的。具体原因参考了躺沙滩上等死的博文

在需要扩容时默认扩容后是原来的2倍,然后将旧容器的所有键值对重新插入新容器。

HashMap和Hashtable

二者都是Map的实现类,区别主要是:

  1. Hashtable是一个**线程安全的Map实现,而HashMap是线程不安全的;所以HashMap性能会高一点。
  2. Hashtable不允许使用null作为key或value,但HashMap允许。
package com.klaus.maps;

import java.util.HashMap;
import java.util.Map;

public class MapTest {
    public static void main(String[] args) {
        Map<Integer,String> map = new HashMap<>();
        System.out.println(map.put(1, "a")); // null
        System.out.println(map.put(2, "b"));// null
        System.out.println(map.put(1, "x"));// a

        System.out.println(map);// {1=x, 2=b}
    }
}

注释的内容是输出结果,正常添加是返回的都是null,而在添加失败时返回key已对应value。

HashMap的迭代方法

Map接口并没有获取Iterator的方法,并且Iterator只适用于Collection,所以说只能获取key的Set集合然后再调用iterator()方法获得迭代器。

//获取迭代器
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
    System.out.println(map.get(iterator.next()));
}

判等原则

HashMap和Hashtable都是只根据equals()的返回结果来去确定

自定义类做key的时候,如果重写equals()和hashCode()方法,就应该保证equals()的结果和hashCode()的结果是一致的,即:equals()返回true时,hashCode()的值应该相等。

对比hashSet,判等不仅要求equals()返回true,还要hashCode()相等。

LinkedHashMap

这是HashMap的子类,与LinkedHashSet类似,它也是用双向链表维护Map。