HashMap和Hashtable的key和value可以为null吗,ConcurrentHashMap呢

🏛️ bt365体育投注官网 ⏳ 2025-11-28 21:22:01 👤 admin 👁️ 8770 💎 384
HashMap和Hashtable的key和value可以为null吗,ConcurrentHashMap呢

文章目录

一、前言二、Hashtable的key为什么不能为null三、HashMap的key为什么可以null四、ConcurrentHashMap的key和value都不能为null五、总结一、前言HashMap的key可以为null,value也可以为nullHashtable的key不允许为null,value也不能为nullConcurrentHashMap的key不允许为null,value也不能为nullHashMap可以存储一个Key为null,多个value为null的元素;但是Hashtable不可以存储二、Hashtable的key为什么不能为null首先来看看Hashtable为什么不允许key为null、value也不能为null

Hashtable的put方法源码为:

代码语言:java复制public synchronized V put(K key, V value) {

// Make sure the value is not null

if (value == null) { //确保value不为null

throw new NullPointerException();

}

// Makes sure the key is not already in the hashtable.

Entry tab[] = table;

int hash = key.hashCode(); //如果key为null,此处会报空指针异常

int index = (hash & 0x7FFFFFFF) % tab.length;

@SuppressWarnings("unchecked")

Entry entry = (Entry)tab[index];

for(; entry != null ; entry = entry.next) {

if ((entry.hash == hash) && entry.key.equals(key)) {

V old = entry.value;

entry.value = value;

return old;

}

}

addEntry(hash, key, value, index);

return null;

}问题出现在 int hash = key.hashCode(),当key为null时,key.hashCode()会报空指针异常同理value为null,throw new NullPointerException() 也会抛出异常所以Hashtable的key、value都不能为空(区别与HashMap的put、hash方法)如果希望允许key为null,就得改写put方法中的hashCode函数,HashMap就是这么实现三、HashMap的key为什么可以null源码分析jdk1.8中,put函数为

代码语言:java复制public V put(K key, V value) {

return putVal(hash(key), key, value, false, true);

}hash(key)就是求key的hashcode,查看源码为

代码语言:java复制static final int hash(Object key) {

int h;

//当key为null的时候,不走hashCode()方法,直接返回0

return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

}当key为null的时候,不走hashCode()方法,直接返回0,不会抛出空指针异常,所以HashMap的key可以为null(与hashtable有区别)

示例:

代码语言:java复制public class MapNull {

public static void main(String[] args) {

Map map1 = new HashMap<>();

map1.put("name", "wj");

map1.put("study", null);

map1.put(null, "unknown");

map1.put(null, null);

System.out.println(map1);

}

}输出 {null=null, study=null, name=wj}

从业务需求上来说HashMap支持 null 键的原因主要是为了提供更大的灵活性和编程便利性。在某些应用场景下,开发者可能需要使用 null 作为键来存储数据。例如在一个系统中,可能存在这样一种情况:某个对象可能没有关联的键,或者出于某种特殊原因,希望用 null 来代表特殊的键值对。允许 null 键的存在使得 HashMap 能够满足这种需求不过需要注意:虽然 HashMap 允许有一个 null 键,但如果有多个线程同时尝试将 null 键插入 HashMap,最终只会有一个键值对能够成功插入(因为键是唯一的)。此外,HashMap 中只能有一个 null 键,但是可以有任意数量的 null 值。

尽管如此,使用 null 键时仍需谨慎,因为它可能会导致代码难以理解和维护,并且在多线程环境下如果没有正确同步,会增加并发问题的风险。

四、ConcurrentHashMap的key和value都不能为nulljdk1.8中,ConcurrentHashMap put函数的源码为:

代码语言:java复制public V put(K key, V value) {

return putVal(key, value, false);

}

/** Implementation for put and putIfAbsent */

final V putVal(K key, V value, boolean onlyIfAbsent) {

// 在此处直接过滤掉key或value为null的情况

if (key == null || value == null) throw new NullPointerException();

// 另外其hash值采用了二次hash,使得hash值分布更均匀

int hash = spread(key.hashCode());

int binCount = 0;

for (Node[] tab = table;;) {

Node f; int n, i, fh;

if (tab == null || (n = tab.length) == 0)

tab = initTable();

else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {

if (casTabAt(tab, i, null,

new Node(hash, key, value, null)))

break; // no lock when adding to empty bin

}

else if ((fh = f.hash) == MOVED)

tab = helpTransfer(tab, f);

else {

V oldVal = null;

synchronized (f) {

if (tabAt(tab, i) == f) {

if (fh >= 0) {

binCount = 1;

for (Node e = f;; ++binCount) {

K ek;

if (e.hash == hash &&

((ek = e.key) == key ||

(ek != null && key.equals(ek)))) {

oldVal = e.val;

if (!onlyIfAbsent)

e.val = value;

break;

}

Node pred = e;

if ((e = e.next) == null) {

pred.next = new Node(hash, key,

value, null);

break;

}

}

}

else if (f instanceof TreeBin) {

Node p;

binCount = 2;

if ((p = ((TreeBin)f).putTreeVal(hash, key,

value)) != null) {

oldVal = p.val;

if (!onlyIfAbsent)

p.val = value;

}

}

}

}

if (binCount != 0) {

if (binCount >= TREEIFY_THRESHOLD)

treeifyBin(tab, i);

if (oldVal != null)

return oldVal;

break;

}

}

}

addCount(1L, binCount);

return null;

}根据源码可知,当key为null、或value为null时,会抛出空指针异常 throw new NullPointerException(),因此ConcurrentHashMap的key和value都不能为null。

五、总结HashMap的key、value都可以为nullhashMap中使用hash()方法来计算key的哈希值,当key为空时,直接令key的哈希值为0,不走key.hashCode()方法;HashMap将键值对添加进数组时,不会主动判断value是否为null(而Hashtable则首先判断value是否为null)hashMap虽然支持key和value为null,但是null作为key只能有一个,null作为value可以有多个因为hashMap中,如果key值一样,那么会覆盖相同key值的value为最新,所以key为null只能有一个Hashtable的key不允许为null,value也不能为null。Hashtable首先判断null是否为null;后续也会直接调用key的hashCode()方法,因此如果key为null,则抛出空指针异常HashMap可以存储一个Key为null,多个value为null的元素;但是Hashtable不可以存储。以上原因主要是由于Hashtable继承自Dictionary,而HashMap继承自AbstractMapConcurrentHashMap的key不允许为null,value也不能为null。虽然ConcurrentHashMap也继承自AbstractMap,但其也过滤掉了key或value为null的键值对。

相关掠夺

bt365体育投注官网
4s店办临时牌照收费吗?4s店办临时牌要多久

4s店办临时牌照收费吗?4s店办临时牌要多久

🗓️ 10-16 👁️ 7928
365bet365娱乐
更新完12.0.1很多软件都不兼容了 真的很烦

更新完12.0.1很多软件都不兼容了 真的很烦

🗓️ 08-30 👁️ 6582
365速发国际平台坑人
24下半年教资面试后多久出成绩?出分后如何拿证?

24下半年教资面试后多久出成绩?出分后如何拿证?

🗓️ 07-06 👁️ 9736