分析HashMap 的 JDK 源码
作者:CodingDiary 时间:2022-01-17 06:29:54
缘由:今天好友拿着下面的代码,问我为什么 Map.Entry 这个接口没有实现 getKey() 和 getValue() 方法,却可以使用,由此,开启了一番查阅 JDK 源码的旅途….
Map map = new HashMap();
map.put(1, "张三");
map.put(2, "李四");
map.put(3, "王五");
map.put(4, "赵六");
map.put(5, "钱七");
Set set = map.entrySet();
for (Object object : set) {
Map.Entry entry = (Map.Entry) object;
System.out.println(entry.getKey() + "-->" + entry.getValue());
}
1.首先,我们看 map 对象,这个 map 对象是 HashMap 的一个实例,然后下面的 Set set = map.entrySet(); 可以知道这其实用的 HashMap 实现的 entrySet() 方法,然后我们可以查看 HashMap 里 entrySet() 的源码
从源码可以看出,这里的返回了一个 EntrySet
对象,但是需要注意的是这个 EntrySet
是 HashMap
里的一个内部类,源码如下:
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() {
return size;
}
public final void clear() {
HashMap.this.clear();
}
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
从这里我们是可以看出,这个 EntrySet
其实是封装的一个 Node
类的实体。也就是说我们的 set
其实就是这个 Node
对象。
2.现在我们来说说这个 Node 对象,Node 对象也是 HashMap 里的一个内部类,源码如下:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
public final String toString() {
return key + "=" + value;
}
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
可以看出来,这个 Node
对象是 Map.Entry<K,V>
的实现类,我们可以看到这个 Node
对象实现了 getKey()
和 getValue()
的方法,所以后面调用的 entry.getKey()
以及 entry.getValue()
方法其实都是调用的 Node 对象里的getKey()
和 getValue()
方法,这里就是 Java 的多态的一种表现。
3.至此,打完收枪!
来源:https://xkcoding.com/2017/07/12/jdk-map-source-explore.html
标签:HashMap,JDK,源码
0
投稿
猜你喜欢
浅析Java编程中枚举类型的定义与使用
2021-07-04 23:46:16
详谈java 堆区、方法区和栈区
2023-11-23 18:35:22
Maven属性与版本管理详细步骤分解
2023-11-15 14:38:45
Java中static关键字的作用和用法详细介绍
2022-07-05 08:33:53
Qt之调用C#的动态库的解决方法
2023-07-22 03:42:45
SpringBoot集成Swagger2的方法
2023-11-26 13:15:42
java中Class.getMethods()和Class.getDeclaredMethods()方法的区别
2021-05-28 23:05:46
Java如何解决发送Post请求报Stream closed问题
2021-12-12 04:20:10
hadoop运行java程序(jar包)并运行时动态指定参数
2023-07-27 11:02:10
Java循环对bean的属性进行赋值的实现
2023-01-27 10:18:05
Java中Controller、Service、Dao/Mapper层的区别与用法
2022-09-12 15:14:03
SpringBoot security安全认证登录的实现方法
2021-05-30 08:09:56
Java Controller实现参数验证与统一异常处理流程详细讲解
2022-01-25 18:49:47
Java 使用poi把数据库中数据导入Excel的解决方法
2022-09-19 14:18:52
Java7到Java17之Switch语句进化史示例详解
2021-11-03 18:47:37
Java中StringUtils与CollectionUtils和ObjectUtil概念讲解
2023-11-29 07:45:38
Java语言读取配置文件config.properties的方法讲解
2023-09-29 14:45:51
详解C++ STL模拟实现forward_list
2023-06-21 02:36:04
springboot对接支付宝支付接口(详细开发步骤总结)
2023-11-10 23:07:35
flutter实现底部导航栏
2023-08-23 01:06:13