记录:295

场景:Java的HashMap理解与应用。把对HashMap操作,从查、增、改、删的角度去理解和应用HashMap的API。

版本:

JDK 1.8
Spring Boot 2.6.3

名词:

API,应用程序接口(Application Programming Interface)。API是一些预定的函数,提供给应用程序访问。调用方无需关注API内部源码和内部工作机制等细节,只需根据API提供方发布的调用方式调用API就行。

一、基础

1.基础知识

(1)HashMap,全称java.util.HashMap。继承java.util.AbstractMap抽象类。实现java.util.Map、java.lang.Cloneable、java.io.Serializable接口。

(2)HashMap的key可以为null,且只能有一个为null的key。可以有多个key值对应的value为null。HashMap的key的需保证唯一性。

(3)HashMap是线程不安全的,在多线程并发的环境下,需要开发人员自己处理多线程的安全问题。

(4)HashMap的数据结构组成是:数组+链表+红黑树。注意本例是(JDK 1.8)。

(5)HashMap、Hashtable、ConcurrentHashMap。HashMap是线程不安全的,多线程并发需自行处理线程安全问题。Hashtable是线程安全,在设计线程安全方法上都添加了synchronized关键字。ConcurrentHashMap是线程安全,效率比Hashtable要高,因为ConcurrentHashMap使用了分段锁,并不对整个数据进行锁定。HashMap的执行效率比Hashtable高。

2.应用场景

在需要使用(key,value)键值对场景均可以使用。在微应用中本地缓存数据、从数据库读取数据以表字段和字段值方式存储时等。

3.函数列表

以下函数主要是java.util.Map接口定义的函数和java.lang.Cloneable接口的clone函数。

//java.util.Map接口函数
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
void clear();
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V>{}
boolean equals(Object o);
int hashCode();
default V getOrDefault(Object key, V defaultValue);
default void forEach(BiConsumer<? super K, ? super V> action);
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
default V putIfAbsent(K key, V value);
default boolean remove(Object key, Object value);
default boolean replace(K key, V oldValue, V newValue);
default V replace(K key, V value);
default V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction);
default V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction);
default V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction);
default V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction);
//java.lang.Cloneable接口函数
public Object clone();

二、应用

1.创建

创建,就是创建ArrayList操作,就能得到一个实际Java对象。

1.1操作场景

操作场景,函数功能说明。

(1)使用new关键字创建HashMap对象实例

1.2操作实例

操作实例,函数应用实例。

/**
 * 使用new关键字创建HashMap对象实例
 */
public static void f_new() {
  // 1.使用new创建默认的HashMap
  Map<String, GirlVo> map01 = new HashMap<>();
  // 2.使用new创建的HashMap,设置容量
  Map<String, GirlVo> map02 = new HashMap<>(100);
  // 3.使用new创建的HashMap,设置容量,设置hash加载因子
  Map<String, GirlVo> map03 = new HashMap<>(100, 0.85f);
  // 4.使用new创建的HashMap,使用一个HashMap作为入参
  Map<String, Object> map0401 = new HashMap<>();
  map0401.put("2001", "杭州");
  map0401.put("2002", "北京");
  Map<String, Object> map04 = new HashMap<>(map0401);
}

2.查

查,就是查询操作。

2.1操作场景

操作场景,函数功能说明。

(1)使用forEach遍历HashMap。

(2)使用for循环和Map.Entry,遍历HashMap,Map.Entry是Map的内部接口。

(3)使用for循环和map.keySet()和map.values(),分别遍历HashMap的key和value,HashMap的所有key转换后存放在Set<K>;所有value转换后存放在Collection<V>。

(4)使用Iterator,遍历HashMap。

(5)使用entrySet和forEach,遍历HashMap。

(6)使用size,查看HashMap存放对象的个数。

(7)使用isEmpty,查看HashMap的size是否为0。

(8)使用containsKey,判断HashMap中是否包含指定的Key。

(9)使用containsValue,判断HashMap中是否包含指定的Value。

(10)使用get,获取HashMap的key对应的value对象。

(11)使用keySet,将HashMap中所有key转换为Set<K>,遍历Set<K>获取每个Key。

(12)使用values,将HashMap中的所有value转换为Collection<V>,遍历Collection<V>获取每个value。

(13)使用entrySet,将HashMap中转换为Set<Map.Entry<K,V>>,遍历结果集。

(14)使用hashCode,计算出HashMap的hashCode值。

(15)使用equals,计算两个HashMap是否相等。

(16)使用getOrDefault,从HashMap中获取key指定对象或者返回默认对象。

(17)使用clone,把HashMap拷贝一份。

2.2操作实例

操作实例,函数应用实例。

/**
 * 1.1 使用forEach遍历HashMap
 */
public static void f1_1() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.遍历HashMap
  map.forEach((key, value) -> {
      System.out.println("gir信息,编号: " + key
              + ",名称: " + value.getGirlName());
  });
}

/**
 * 1.2 使用for循环和Map.Entry,遍历HashMap,Map.Entry是Map的内部接口
 */
public static void f1_2() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.遍历HashMap
  for (Map.Entry<String, GirlVo> entry : map.entrySet()) {
      System.out.println("girl编号: " + entry.getKey()
      + ",girl信息: " + entry.getValue());
  }
}

/**
 * 1.3 使用for循环和map.keySet()和map.values(),遍历HashMap
 */
public static void f1_3() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.遍历HashMap的key
  for (String key : map.keySet()) {
      System.out.println("key: " + key);
  }
  // 3.遍历HashMap的value
  for (GirlVo value : map.values()) {
      System.out.println("value: " + value);
  }
}

/**
 * 1.4 使用Iterator,遍历HashMap
 */
public static void f1_4() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.遍历HashMap
  Iterator<Map.Entry<String, GirlVo>> iterator = map.entrySet().iterator();
  while (iterator.hasNext()) {
      Map.Entry<String, GirlVo> entry = iterator.next();
      System.out.println("girl编号: " + entry.getKey()
              + ",girl信息: " + entry.getValue());
  }
}

/**
 * 1.5 使用entrySet和forEach,遍历HashMap
 */
public static void f1_5() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.遍历HashMap
  map.entrySet().forEach(entry -> {
      System.out.println("key: " + entry.getKey()
              + ",value: " + entry.getValue());
  });
}

/**
 * 1.6 使用size,查看HashMap存放对象的个数
 */
public static void f1_6() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.查看HashMap的size
  int size = map.size();
  // 3.打印结果
  System.out.println("size = " + size);
}

/**
 * 1.7 使用isEmpty,查看HashMap的size是否为0
 */
public static void f1_7() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.查看HashMap是否为空
  boolean flag = map.isEmpty();
  // 3.打印结果
  System.out.println("result = " + flag);
}

/**
 * 1.8 使用containsKey,判断HashMap中是否包含指定的Key
 */
public static void f1_8() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.查看是否包含指定的key
  boolean flag = map.containsKey("1001");
  // 3.打印结果
  System.out.println("result = " + flag);
}

/**
 * 1.9 使用containsValue,判断HashMap中是否包含指定的Value
 */
public static void f1_9() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.判断是否包含对象
  boolean flag = map.containsValue("杭州");
  // 3.打印结果
  System.out.println("result = " + flag);
}

/**
 * 1.10 使用get,获取HashMap的key对应的value对象
 */
public static void f1_10() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.获取对象
  GirlVo girl = map.get("1001");
  // 3.打印结果
  System.out.println("result = " + girl);
}

/**
 * 1.11 使用keySet,将HashMap中所有key转换为Set<K>,遍历Set<K>获取每个Key
 */
public static void f1_11() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.获取Set<String>
  Set<String> set = map.keySet();
  // 3.打印结果
  for (String key : map.keySet()) {
      System.out.println("key: " + key);
  }
}

/**
 * 1.12 使用values,将HashMap中的所有value转换为Collection<V>,遍历Collection<V>获取每个value
 */
public static void f1_12() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.获取Collection<GirlVo>
  Collection<GirlVo> collection = map.values();
  // 3.打印结果
  for (GirlVo girlVo : collection) {
      System.out.println("girlVo: " + girlVo.toString());
  }
}

/**
 * 1.13 使用entrySet,将HashMap中转换为Set<Map.Entry<K,V>>,遍历结果集.
 * Entry<K,V>是Map的内部接口
 */
public static void f1_13() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.使用entrySet将HashMap中转换为Set<Map.Entry<K,V>>
  Set<Map.Entry<String, GirlVo>> entrySet = map.entrySet();
  // 3.打印结果
  for (Map.Entry<String, GirlVo> entry : entrySet) {
      System.out.println("key: " + entry.getKey() + ",value: " + entry.getValue());
  }
}

/**
 * 1.14 使用equals,计算两个HashMap是否相等
 */
public static void f1_14() {
  // 1.获取HashMap
  Map<String, Object> map01 = getMapCity();
  Map<String, Object> map02 = getMapCity();
  // 2.计算是否相等
  boolean flag = map01.equals(map02);
  // 3.打印结果
  System.out.println("城市: " + flag);
}

/**
 * 1.15 使用hashCode,计算出HashMap的hashCode值
 */
public static void f1_15() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.计算hashCode
  int hash = map.hashCode();
  // 3.打印结果
  System.out.println("城市: " + hash);
}

/**
 * 1.16 使用getOrDefault,从HashMap中获取key指定对象或者返回默认对象
 */
public static void f1_16() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.从HashMap中获取key指定对象或者返回默认对象
  Object city = map.getOrDefault("1007", "厦门");
  // 3.打印结果
  System.out.println("城市: " + city);
}

/**
 * 1.17 使用clone,把HashMap拷贝一份
 */
public static void f1_17() {
  // 1.获取HashMap
  HashMap<String, Object> map01 = getHashMapCity();
  HashMap<String, Object> map02 = null;
  // 2.使用clone克隆
  map02 = (HashMap<String, Object>) map01.clone();
  // 3.打印结果
  map02.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

3.增

增,就是增加操作。

3.1操作场景

操作场景,函数功能说明。

(1)使用put,在HashMap增加一条数据,如果Key存在,则会覆盖Value。

(2)使用putAll,在HashMap添加一个Map。

(3)使用putIfAbsent,在HashMap添加一个对象,如果Key存在,则不会覆盖Value。

3.2操作实例

操作实例,函数应用实例。

/**
 * 2.1 使用put,在HashMap增加一条数据,如果Key存在,则会覆盖Value
 */
public static void f2_1() {
  // 1.创建HashMap
  Map<String, Object> map = new HashMap<>();
  // 2.新增一条数据
  map.put("1001", "杭州");
  map.put("1002", "北京");
}

/**
 * 2.2 使用putAll,在HashMap添加一个Map
 */
public static void f2_2() {
  // 1.创建HashMap对象map01
  Map<String, Object> map01 = new HashMap<>();
  map01.put("1001", "杭州");
  map01.put("1002", "北京");
  // 2.创建HashMap对象map02
  Map<String, Object> map02 = new HashMap<>();
  map02.put("1003", "厦门");
  // 3.使用putAll把map01添加到map02
  map02.putAll(map01);
  // 4.遍历map02
  map02.forEach((key, value) -> {
      System.out.println(",编号: " + key
              + ",名称: " + value);
  });
}

/**
 * 2.3 使用putIfAbsent,在HashMap添加一个对象,如果Key存在,则不会覆盖Value
 */
public static void f2_3() {
  // 1.创建HashMap对象map01
  Map<String, Object> map01 = new HashMap<>();
  map01.put("1001", "杭州");
  map01.put("1002", "北京");
  // 2.使用putIfAbsent添加一个对象,如果Key存在,则不会覆盖Value
  Object obj01 = map01.putIfAbsent("1003", "厦门");
  Object obj02 = map01.putIfAbsent("1001", "苏州");
  // 3.遍历map01
  map01.forEach((key, value) -> {
      System.out.println("编号: " + key
              + ",名称: " + value);
  });
}

4.改

改,就是修改操作。

4.1操作场景

操作场景,函数功能说明。

(1)使用replace,修改HashMap中指定key的value值

(2)使用replace,查找出HashMap中,指定的key的curValue,如果replace的入参oldValue和curValue相等,则执行put(key,newValue),把入参newValue替换掉原来对应的值。

(3)使用replaceAll,以函数式接口方式,修改指定key的value值。

(4)使用computeIfAbsent,取出HashMap的key对应value值,value为null,则把函数式接口里面值put到HashMap;value不为null,则不操作,直接返回key对应的value。

(5)使用computeIfAbsent,取出HashMap的key对应value值,value不为null,则把函数式接口的apply返回的新值put到HashMap;value为null,则不操作,直接返回null。

(6)使用compute,取出HashMap的key对应value值,函数式接口的apply返回的新值newValue,新值newValue为null,则根据key删除HashMap中(key,value),新值newValue为不null,则put(key,newValue)。

(7)使用merge,取出HashMap的key对应oldValue值,oldValue为null,则使用传入的value值,不为null则使用函数式接口的apply返回值,作为newValue,newValue为null,则使用remove(key)删除,newValue不为null,则使用put(key,newValue)。

4.2操作实例

操作实例,函数应用实例。

/**
 * 3.1 使用replace,修改HashMap中指定key的value值
 */
public static void f3_1() {
  // 1.获取HashMap
  Map<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  // 2.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.修改一条数据
  Object obj = map.replace("1001", "苏州");
  // 4.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

/**
 * 3.2 使用replace,查找出HashMap中,指定的key的curValue,
 * 如果replace的入参oldValue和curValue相等,则执行put(key,newValue),把入参newValue替换掉原来对应的值
 */
public static void f3_2() {
  // 1.获取HashMap
  Map<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  // 2.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.修改一条数据
  boolean flag = map.replace("1001", "杭州", "苏州");
  // 4.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

/**
 * 3.3 使用replaceAll,以函数式接口方式,修改指定key的value值
 */
public static void f3_3() {
  // 1.获取HashMap
  Map<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  // 2.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.修改一条数据
  map.replaceAll((key, value) -> {
      if (Objects.equals(key, "1001")) {
          value = "厦门";
      }
      return value;
  });
  // 4.修改前遍历
  System.out.println("修改前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

/**
 * 3.4 使用computeIfAbsent,取出HashMap的key对应value值,
 * value为null,则把函数式接口里面值put到HashMap;
 * value不为null,则不操作,直接返回key对应的value
 */
public static void f3_4() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  map.put("1009", null);
  // 2.执行computeIfAbsent操作
  Object city = map.computeIfAbsent("1009", (key) -> {
      return "宁波";
  });
  // 3.打印结果
  System.out.println("城市: " + city);
}

/**
 * 3.5 使用computeIfAbsent,取出HashMap的key对应value值,
 * value不为null,则把函数式接口的apply返回的新值put到HashMap;
 * value为null,则不操作,直接返回null
 */
public static void f3_5() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.执行computeIfPresent操作
  Object city = map.computeIfPresent("1001", (key, value) -> {
      if (Objects.equals(value, "杭州")) {
          return "杭州A";
      }
      return value;
  });
  // 3.打印结果
  System.out.println("城市: " + city);
}

/**
 * 3.6 使用compute,取出HashMap的key对应value值,
 * 函数式接口的apply返回的新值newValue,
 * 新值newValue为null,则根据key删除HashMap中(key,value),
 * 新值newValue为不null,则put(key,newValue)
 */
public static void f3_6() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.新值不为null
  Object city01 = map.compute("1009", (key, value) -> {
      return "厦门";
  });
  // 3.新值为null
  Object city02 = map.compute("1001", (key, value) -> {
      if (Objects.equals("杭州", value)) {
          return null;
      }
      return value;
  });
  // 4.打印结果
  System.out.println("城市: " + city01);
}

/**
 * 3.7 使用merge,取出HashMap的key对应oldValue值,
 * oldValue为null,则使用传入的value值,不为null则使用函数式接口的apply返回值,作为newValue,
 * newValue为null,则使用remove(key)删除,
 * newValue不为null,则使用put(key, newValue)
 */
public static void f3_7() {
  // 1.获取HashMap
  Map<String, Object> map = getMapCity();
  // 2.新值不为null
  Object city01 = map.merge("1009", "南京", (oldValue, value) -> {
      return "南京";
  });
  // 3.打印结果
  System.out.println("城市: " + city01);
}

5.删

删,就是删除操作。

5.1操作场景

操作场景,函数功能说明。

(1)使用remove,删除HashMap中一个对象,返回一个已经删除的对象。

(2)使用remove,删除HashMap中一个对象。

(3)使用clear,删除HashMap所有对象。

5.2操作实例

操作实例,函数应用实例。

/**
 * 4.1 使用remove,删除HashMap中一个对象,返回一个已经删除的对象
 */
public static void f4_1() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.删除前遍历
  System.out.println("删除前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.删除一条数据,返回删除的对象
  Object obj = map.remove("1001");
  // 4.删除后遍历
  System.out.println("删除后遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

/**
 * 4.2 使用remove,删除HashMap中一个对象
 */
public static void f4_2() {
  // 1.获取HashMap
  Map<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  // 2.删除前遍历
  System.out.println("删除前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.删除一条数据,返回true,已经成功,返回false,没删除
  boolean flag = map.remove("1001", "北京");
  // 4.删除后遍历
  System.out.println("删除后遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

/**
 * 4.3 使用clear,删除HashMap所有对象
 */
public static void f4_3() {
  // 1.获取HashMap
  Map<String, GirlVo> map = getMap();
  // 2.删除前遍历
  System.out.println("删除前遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
  // 3.删除所有对象
  map.clear();
  // 4.删除后遍历
  System.out.println("删除后遍历:");
  map.forEach((key, value) -> {
      System.out.println("key: " + key + " ,value: " + value);
  });
}

6.共用代码

6.1获取数据

(1)获取Map<String, GirlVo>。

(2)获取Map,包含编码和城市。

(3)获取HashMap,包含编码和城市。

/**
 * 获取Map<String, GirlVo>
 * */
public static Map<String, GirlVo> getMap() {

  Map<String, GirlVo> map = new HashMap<>();
  GirlVo girl01 = GirlVo.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
  GirlVo girl02 = GirlVo.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
  GirlVo girl03 = GirlVo.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
  GirlVo girl04 = GirlVo.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
  GirlVo girl05 = GirlVo.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
  GirlVo girl06 = GirlVo.builder().girlId("1006").girlName("张八").age(26).height(165).cupSize("A").build();
  map.put(girl01.getGirlId(), girl01);
  map.put(girl02.getGirlId(), girl02);
  map.put(girl03.getGirlId(), girl03);
  map.put(girl04.getGirlId(), girl04);
  map.put(girl05.getGirlId(), girl05);
  map.put(girl06.getGirlId(), girl06);
  return map;
}

/**
 * 获取Map,包含编码和城市
 */
public static Map<String, Object> getMapCity() {
  Map<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  map.put("1003", "苏州");
  return map;
}

/**
 * 获取HashMap,包含编码和城市
 */
public static HashMap<String, Object> getHashMapCity() {
  HashMap<String, Object> map = new HashMap<>();
  map.put("1001", "杭州");
  map.put("1002", "北京");
  map.put("1003", "苏州");
  return map;
}

6.2JavaBean对象

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GirlVo {
  /**ID号*/
  String girlId;
  /**姓名*/
  String girlName;
  /**年龄*/
  long age;
  /**身高*/
  double height;
  /**罩杯*/
  String cupSize;
}

以上,感谢。

2022年9月23日

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐