面试高频考点:HashMap

89 阅读2分钟

定义

  • Hash table based implementation of the Map interface (基于哈希表的Map接口实现)

什么是哈希表

  • 设计精妙、用途广泛的数据结构之一
  • 拥有键值对元素的无序集合
  • 键的值是唯一的,键对应的值可以通过键来获取、更新或移除
  • 无论这个哈希表有多大,这些操作(Insert/Search/Delete)基本上通过常量时机 O(1) 的键比较就可完成

HashMap 实战

  • 如何构造一个 HashMap
Map<String, Double> map = new HashMap<>();
  • size/isEmpty
System.out.println("Size of map: " + map.size());   // 0
System.out.println("IsEmpty result: " + map.isEmpty());
  • 【重点】put/putAll/putIfAbsent
//1. put:把键值对放入 hash map(包含增和改)
Double oldValue = map.put("abc", 2.3); // null -> add
System.out.println("The value of abc: " + oldValue);
System.out.println("The current value of abc: " + map.get("abc"));
oldValue = map.put("abcd", 2.56);      // null -> add
System.out.println("The value of abcd: " + oldValue);
System.out.println("The current value of abcd: " + map.get("abcd"));
// 覆盖原来的键值对,除非你明确地知道要去更新键值对的时候,可以用重复的key调用put方法(更新)
oldValue = map.put("abc", 2.5);        // 2.3 (old value) -> update
System.out.println("2nd: The value of abc: " + oldValue);
System.out.println("The current value of abc: " + map.get("abc"));

// 特例
oldValue = map.put(null, null);
System.out.println("The value of null: " + oldValue);
oldValue = map.put(null, null);
System.out.println("The value of null: " + oldValue);

// 2. putIfAbsent:map.get(key) 为 null,就把 key-value 放入 map,否则返回 key 之前对应的 value
Double v = map.putIfAbsent("abc", 10.22); // 2.5
System.out.println("v of abc: " + v);
v = map.putIfAbsent("a", 111.11); // null -> add
System.out.println("v of abc: " + v);
System.out.println("The value of key a: " + map.get("a"));

// 3. putAll 一般情况不建议使用
System.out.println("The value of key d before putAll: " + map.get("d"));
System.out.println("The value of key e before putAll: " + map.get("e"));
System.out.println("The value of key a before putAll: " + map.get("a"));
Map<String, Double> newMap = new HashMap<>();
newMap.put("d", 100.12);
newMap.put("e", 100.13);
newMap.put("a", 0.1);
map.putAll(newMap);
System.out.println("The value of key d: " + map.get("d"));
System.out.println("The value of key e: " + map.get("e"));
System.out.println("The value of key a: " + map.get("a"));
  • 【重点】get/getOrDefault
// 1. get方法:(1)key在map中:对于传入的key,存在value,返回这个value (2)key不在map中:对于传入的key,不存在对应的键值对,就返回空
Double valueOfABC = map.get("abc");
System.out.println();
System.out.println("The value of key abc: " + valueOfABC);

Double valueOfJava = map.get("java");
System.out.println("The value of key java: " + valueOfJava);

// 特例
map.put("jirengu", null);
System.out.println("The value of key jirengu: " + map.get("jirengu"));

// 2. getOrDefault
Double valueOfMethodGetOrDefault = map.getOrDefault("a", 10.05);
System.out.println("The value of getOrDefault for key a: " + valueOfMethodGetOrDefault);

valueOfMethodGetOrDefault = map.getOrDefault("method", 0.333333);
System.out.println("The value of getOrDefault for key method: " + valueOfMethodGetOrDefault);
  • 【重点】containsKey/containsValue
// containsKey/containsValue
System.out.println("The result of a: " + map.containsKey("a"));  // true
System.out.println("The result of a: " + map.containsKey("method"));  // false

System.out.println("The result of a: " + map.containsValue(2.5));  // true
System.out.println("The result of a: " + map.containsValue(0.11111111));  // false
System.out.println("The result of a: " + map.containsValue(2.3));  // false
  • remove
Double valueToRemove = map.remove("a"); // 0.1
System.out.println("Value to remove for key a: " + valueToRemove);
System.out.println("The value of key a: " + map.get("a"));
valueToRemove = map.remove("method"); // null
System.out.println("Value to remove for key method: " + valueToRemove);

boolean isSuccess = map.remove("abc", 100.01);
System.out.println("Flag isSuccess: " + isSuccess);
System.out.println("Size of map: " + map.size());
System.out.println("The value of key abc: " + map.get("abc"));
isSuccess = map.remove("abc", 2.5);
System.out.println("Flag isSuccess: " + isSuccess);
System.out.println("Size of map: " + map.size());
System.out.println("The value of key abc: " + map.get("abc"));
  • replace/replaceAll
// replace -> 代替put做更新操作,只用于更新,如果key不存在,返回null
oldValue = map.replace("e", 0.55);  // 0.1
System.out.println("The old value before replacing for key a: " + oldValue);
System.out.println("The current value for key a: " + map.get("e"));
  • 【重点】keySet/values/entrySet
Set<String> keys = map.keySet();
for (String key: keys) {
    System.out.println("The key in map: " + key);
}

Collection<Double> values = map.values();
for (Double value: values) {
    System.out.println("The value in map: " + value);
}

Set<Map.Entry<String, Double>> entries = map.entrySet();
for (Map.Entry<String, Double> entry : entries) {
    String key = entry.getKey();
    Double value = entry.getValue();
    System.out.println("The entry in map: " + key + " value: " + value);
}
  • 【重点】如何遍历 HashMap
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 100);
map.put(2, 200);
map.put(3, 300);
map.put(4, 400);
map.put(5, 500);

// 遍历HashMap
// 1. 遍历entry
for (Map.Entry<Integer, Integer> m : map.entrySet()) {
    System.out.println("EntrySet key: " + m.getKey() + " Value: " + m.getValue());
}

// 2. 通过keySet()遍历key,然后利用map.get(key)获取value
for (Integer key : map.keySet()) {
    System.out.println("KeySet key: " + key + " Value: " + map.get(key));
}

// 3. 利用迭代器 set的迭代器 (一般工作中较少用到)
// (1) 利用entrySet()迭代器
Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
    Map.Entry<Integer, Integer> entry = iterator.next();
    System.out.println("EntrySet Iterator Key: " + entry.getKey() + " Value: " + entry.getValue());
}

// (2) 里利用keySet()迭代器,然后利用map.get(key)获取value
Iterator<Integer> keyIterator = map.keySet().iterator();
while (keyIterator.hasNext()) {
    Integer key = keyIterator.next();
    System.out.println("KeySet Iterator Key: " + key + " Value: " + map.get(key));
}

// 4. lambda Java8
map.forEach((k, v) -> System.out.println("Lambda Foreach key: " + k + " Value: " + v));
// 啰嗦
map.entrySet().forEach(entry -> System.out.println("Lambda Entry key: " + entry.getKey() + " value: " + entry.getValue()));
map.keySet().forEach(k -> System.out.println("Key: " + k + " Value: " + map.get(k)));