Core Java Tutorial -,corejavatutorial
Core Java Tutorial -,corejavatutorial
Java HashMap 是 Java 最流行的集合类之一。Java HashMap 是基于哈希表实现的。HashMap 扩展于实现 Map 接口的 AbstractMap 类。
Java HashMap
Java 中有关 HashMap 的一些重要观点有:
Java HashMap Constructors
Java HashMap 提供四个构造器:
Java HashMap Constructors Example
下面的代码片段显示了使用上述所有构造函数的 HashMap 示栗。
Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>(2 ^ 5);
Map<String, String> map3 = new HashMap<>(32, 0.80f);
Map<String, String> map4 = new HashMap<>(map1);
}
Java HashMap Methods
让我们来看一下 HashMap 的一些重要方法:
Java 8 引入了很多新的 HashMap 方法。
Java HashMap Example
HashMap 常用方法示栗:
package HashMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>(); // Java 10 new feature
map.put("1", "1"); // put example
map.put("2", "2");
map.put("3", "3");
map.put("4", null); // null value
map.put(null, "100"); // null key
String value = map.get("3"); // get example
System.out.println("Key = 3, Value = " + value);
value = map.getOrDefault("5", "Default Value");
System.out.println("Key = 5, Value= " + value);
boolean keyExists = map.containsKey(null);
boolean valueExists = map.containsValue("100");
System.out.println("keyExists = " + keyExists + ", valueExists =" + valueExists);
Set<Map.Entry<String, String>> entrySet = map.entrySet();
System.out.println(entrySet);
System.out.println("map size =" + map.size());
Map<String, String> map1 = new HashMap<>();
map1.putAll(map);
System.out.println("map1 mappings = " + map1);
String nullKeyValue = map1.remove(null);
System.out.println("map1 null key value = " + nullKeyValue);
System.out.println("map1 after removing null key = " + map1);
Set<String> keySet = map.keySet();
System.out.println("map keys = " + keySet);
Collection<String> values = map.values();
System.out.println("map values = " + values);
map.clear();
System.out.println("map is empty=" + map.isEmpty());
}
}
输出结果:
Key = 3, Value = 3
Key = 5, Value= Default Value
keyExists = true, valueExists =true
[null=100, 1=1, 2=2, 3=3, 4=null]
map size =5
map1 mappings = {null=100, 1=1, 2=2, 3=3, 4=null}
map1 null key value = 100
map1 after removing null key = {1=1, 2=2, 3=3, 4=null}
map keys = [null, 1, 2, 3, 4]
map values = [100, 1, 2, 3, null]
map is empty=true
How HashMap works in java?
Java 中的 HashMap 使用它内部类 Node<K, V>
来存储映射,HashMap 运行在散列算法上,对键的 get 和 put 操作采用 hashCode()
和 equals()
方法。
HashMap 使用单链表存储元素,这些元素被称为仓或桶。当我们调用 put 方法,键的 hasCode 方法被用来确定将用于存储映射的存储桶。
一旦桶确定了,hashCode 方法用来检查是否已经存在相同 hashCode 的键。如果存在,将 equals()
方法将被对键使用。如果 equals() 方法返回 true,就覆盖其值。否则在单链桶中创建新映射。如果没有具有相同 hashCode 的键,则将映射插入到存储桶中。
对于 HashMap get 操作,在此使用 key 的 hashCode 来确定要查找该值的存储区。在确定桶之后,使用 hashCode 和 equals 方法查找遍历条目来查找条目。如果找到匹配,则返回值,否则返回 null。
还涉及更多的事情,栗如哈希算法来获取键的桶,映射的重散列等。但是对于我们,只要记住 HashMap 操作对 Key 有效,并且需要 hashCode 和 equals 方法的良好实现以避免不需要的行为。
建议阅读:hashCode and equals method importance in Java
Java HashMap Load Factor
加载因子用来计算何时重新映射 HashMap 并增加桶大小。桶的默认值或容量是 16,加载因子是 0.75。重散列的阈值时通过容量和加载因子相乘计算的。所以默认阈值是 12。因此,当 HashMap 具有多个于 12 个是映射时,其将被重散列并且桶的数量将被增加到下一幂,即 32。注意,HashMap 容量始终为 2 的幂。
Java HashMap keySet
Java HashMap keySet 方法返回 HashMap 中键的 Set 集合视图。此 Set 集合视图由 HashMap 支持,并且 HashMap 中的任何更改都反映在 Set 中,反之亦然。下面是一个演示 HashMap keySet 示栗的简单程序,如果你希望 keySet 不由 Map 支持,那么该怎么办。
package HashMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class HashMapKeySetExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
Set<String> keySet = map.keySet();
System.out.println(keySet);
map.put("4", "4");
System.out.println(keySet); // keySet is backed by Map
keySet.remove("1");
System.out.println(map); // map is also modified
keySet = new HashSet<>(map.keySet()); // copies the key to new Set
map.put("5", "5");
System.out.println(keySet); // keySet is not modified
}
}
输出结果:
[1, 2, 3]
[1, 2, 3, 4]
{2=2, 3=3, 4=4}
[2, 3, 4]
Java HashMap values
Java HashMap values 方法返回一个 Map 中值的 Collection 集合视图。这个集合由 HashMap 支持,所以 HashMap 中的任何值得更改都反映在 Set 中,反之亦然。下面的一个简单示例确认了 HashMap values Collection 的这种行为。
package HashMap;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class HashMapValuesExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", "2");
map.put("3", null);
map.put("4", null);
map.put(null, "100");
Collection<String> values = map.values();
System.out.println("map values = " + values);
map.remove(null);
System.out.println("map values after removing null key = " + values);
map.put("5", "5");
System.out.println("map values after put = " + values);
System.out.println(map);
values.remove("1"); // changing values collection
System.out.println(map); // updates in map too
}
}
输出:
map values = [100, 1, 2, null, null]
map values after removing null key = [1, 2, null, null]
map values after put = [1, 2, null, null, 5]
{1=1, 2=2, 3=null, 4=null, 5=5}
{2=2, 3=null, 4=null, 5=5}
Java HashMap entrySet
Java HashMap entrySet 方法返回映射的 Set 集合视图。这个 entrySet 由 HashMap 支持,所以任何在 Map 中的修改都会反映到 entrySet 中,反之亦然。来看下下面 HashMap entrySet 示栗程序。
package HashMap;
import java.util.*;
import java.util.Map.Entry;
public class HashMapEntrySetExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
Set<Entry<String, String>> entrySet = map.entrySet();
Iterator<Entry<String, String>> iterator = entrySet.iterator();
Entry<String, String> next = null;
System.out.println("map before processing = " + map);
System.out.println("entrySet before processing = " + entrySet);
while (iterator.hasNext()) {
next = iterator.next();
System.out.println("Processing on: " + next.getValue());
if (next.getKey() == null) {
iterator.remove();
}
}
System.out.println("map after processing = " + map);
System.out.println("entrySet after processing = " + entrySet);
//Entry simpleEntry = new AbstractMap.SimpleEntry<>("1", "1");
var simpleEntry = new AbstractMap.SimpleEntry<>("1", "1");
entrySet.remove(simpleEntry);
System.out.println("map after removing Entry = " + map);
System.out.println("entrySet after removing Entry = " + entrySet);
}
}
输出如下:
map before processing = {null=100, 1=1, 2=null}
entrySet before processing = [null=100, 1=1, 2=null]
Processing on: 100
Processing on: 1
Processing on: null
map after processing = {1=1, 2=null}
entrySet after processing = [1=1, 2=null]
map after removing Entry = {2=null}
entrySet after removing Entry = [2=null]
Java HashMap putIfAbsent
Java 8 中引入的 HashMap putIfAbsent 方法简单示栗:
package HashMap;
import java.util.HashMap;
import java.util.Map;
public class HashMapPutIfAbsentExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
System.out.println("map before putIfAbsent = " + map);
String value = map.putIfAbsent("1", "4");
System.out.println("map after putIfAbsent = " + map);
System.out.println("putIfAbsent returns: " + value);
System.out.println("map before putIfAbsent = " + map);
value = map.putIfAbsent("3", "3");
System.out.println("map after putIfAbsent = " + map);
System.out.println("putIfAbsent returns: " + value);
}
}
输出结果:
map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null}
putIfAbsent returns: 1
map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null, 3=3}
putIfAbsent returns: null
Java HashMap forEach
Java 8 中引入了 HashMap forEach 方法。这是个非常的方法,用来对 Map 中的每个条目执行给定操作。直到处理完所有条目或操作抛出异常为止。
package HashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class HashMapForEachExample {
public static void main(String[] args) {
//Map<String, String> map = new HashMap<>();
var map = new HashMap<String, String>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
BiConsumer<String, String> action = new MyBiConsumer();
map.forEach(action);
//lambda expression example
System.out.println("\nHashMap forEach lambda example\n");
map.forEach((k, v) ->
System.out.println("Key = " + k + ", Value = " + v));
}
}
class MyBiConsumer implements BiConsumer<String, String> {
@Override
public void accept(String t, String u) {
System.out.println("Key = " + t);
System.out.println("Processing on value = " + u);
}
}
输出结果:
Key = null
Processing on value = 100
Key = 1
Processing on value = 1
Key = 2
Processing on value = null
HashMap forEach lambda example
Key = null, Value = 100
Key = 1, Value = 1
Key = 2, Value = null
Java HashMap replaceAll
HashMap replaceAll 方法可用于用调用该条目上的给定函数的结果替换每个条目的值。这个方法在 Java 8 中添加,我们可以使用 lambda 表达式来表示这个方法参数。
package HashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class HashMapReplaceAllExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "100");
System.out.println("map before replaceAll = " + map);
BiFunction<String, String, String> function = new MyBiFunction();
map.replaceAll(function);
System.out.println("map after replaceAll = " + map);
// replaceAll using lambda expressions
map.replaceAll((k, v) -> {
if (k != null) return k + v;
else return v;
});
System.out.println("map after replaceAll lambda expression = " + map);
}
}
class MyBiFunction implements BiFunction<String, String, String> {
@Override
public String apply(String t, String u) {
if (t != null)
return t + u;
else
return u;
}
}
输出:
map before replaceAll = {null=100, 1=1, 2=2}
map after replaceAll = {null=100, 1=11, 2=22}
map after replaceAll lambda expression = {null=100, 1=111, 2=222}
Java HashMap computeIfAbsent
HashMap computeIfAbsent 方法仅在键不存在于 Map 中时才计算该值。计算完值后,如果它不为 null,则将其放入地图中。
package HashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class HashMapComputeIfAbsent {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "10");
map.put("2", "20");
map.put(null, "100");
Function<String, String> function = new MyFunction();
map.computeIfAbsent("3", function); // key not present
map.computeIfAbsent("2", function); // key already present
//lambda way
map.computeIfAbsent("4", v -> v);
map.computeIfAbsent("5", v -> null); // null value won't get inserted
System.out.println(map);
}
}
class MyFunction implements Function<String, String> {
@Override
public String apply(String t) {
return t;
}
}
输出:
{null=100, 1=10, 2=20, 3=3, 4=4}
Java HashMap computeIfPresent
Java HashMap computeIfPresent 方法在指定的键存在且值不为空时重新计算值。如果该函数返回 null,则映射将被删除。
package HashMap;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class HashMapComputeIfPresentExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "10");
map.put("2", "20");
map.put(null, "100");
map.put("10", null);
System.out.println("map before computeIfPresent = " + map);
BiFunction<String, String, String> function = new MyBiFunction1();
for (String key : map.keySet()) {
map.computeIfPresent(key, function);
}
System.out.println("map after computeIfPresent = " + map);
map.computeIfPresent("1", (k, v) -> null); // mapping will be removed
System.out.println("map after computeIfPresent = " + map);
}
}
class MyBiFunction1 implements BiFunction<String, String, String> {
@Override
public String apply(String t, String u) {
return t + u;
}
}
输出:
map before computeIfPresent = {null=100, 1=10, 2=20, 10=null}
map after computeIfPresent = {null=null100, 1=110, 2=220, 10=null}
map after computeIfPresent = {null=null100, 2=220, 10=null}
Java HashMap compute
如果你想基于它的键和值在所有的映射上应用一个函数,那么应该使用计算方法。如果没有映射并且使用此方法,则计算函数的值将为空。
package HashMap;
import java.util.HashMap;
import java.util.Map;
public class HashMapComputeExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "10");
map.put("10", null);
System.out.println("map before compute = " + map);
for (String key : map.keySet()) {
map.compute(key, (k, v) -> k + v);
}
map.compute("5", (k, v) -> k + v); //key not present, v = null
System.out.println("map after compute = " + map);
}
}
输出:
map before compute = {null=10, 1=1, 2=2, 10=null}
map after compute = {null=null10, 1=11, 2=22, 5=5null, 10=10null}
Java HashMap merge
如果指定键不存在或者与空关联,则将其与给定的非空值相关联。否则,否则,使用给定的重映射函数的结果替换关联的值,或者如果结果为 null ,则将其删除。
package HashMap;
import java.util.HashMap;
import java.util.Map;
public class HashMapMergeExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "10");
map.put("10", null);
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
//merge throws NullPointerException if key or value is null
if (key != null && value != null)
map.merge(entry.getKey(), entry.getValue(),
(k, v) -> k + v);
}
System.out.println(map);
map.merge("5", "5", (k, v) -> k + v); // key not present
System.out.println(map);
map.merge("1", "1", (k, v) -> null); // method return null, so remove
System.out.println(map);
}
}
输出:
{null=10, 1=11, 2=22, 10=null}
{null=10, 1=11, 2=22, 5=5, 10=null}
{null=10, 2=22, 5=5, 10=null}
相关文章
- 暂无相关文章
用户点评