Java 为什么不再在HashMap.clear()中使用Arrays.fill()?
我注意到Java 为什么不再在HashMap.clear()中使用Arrays.fill()?,java,arrays,hashmap,java-8,Java,Arrays,Hashmap,Java 8,我注意到HashMap.clear()的实现有些奇怪。这是它的外观: 这就是它的外观: public void clear(){ 节点[]选项卡; modCount++; 如果((制表符=表格)!=null&&size>0){ 尺寸=0; 对于(int i=0;i潜在的绩效收益并不是那么微不足道的,如果你考虑所有涉及的事情: JVM不需要解析数组类,也不需要在需要时加载和初始化它。这是一个非常重要的过程,JVM执行几个步骤。首先,它检查类加载器以查看类是否已经加载,并且每次调用方法时都会发生这种
HashMap.clear()
的实现有些奇怪。这是它的外观:
这就是它的外观:
public void clear(){
节点[]选项卡;
modCount++;
如果((制表符=表格)!=null&&size>0){
尺寸=0;
对于(int i=0;i
我知道现在对于空映射,表
可以为null,因此需要在局部变量中进行额外的检查和缓存。但是为什么用for循环替换了Arrays.fill()
这一变化似乎是在年引入的。不幸的是,我没有找到解释为什么普通for循环可能比
Arrays.fill()
更好。速度快吗?还是更安全?两个版本的循环在功能上没有实际差异<代码>数组。填充执行完全相同的操作
因此,使用与否的选择不一定被认为是错误的。当涉及到这种微观管理时,由开发人员决定
每种方法都有两个单独的关注点:
- 使用
可以减少代码的冗长程度,提高代码的可读性Arrays.fill
- 直接在
代码(如版本8)中循环性能方面实际上是一个更好的选择。虽然插入HashMap
类的开销可以忽略不计,但当涉及到像数组
这样的广泛应用时,它的开销可能会更小,在这种应用中,每一点性能增强都会产生巨大的影响(想象一下,在成熟的webapp中,HashMap的最小占用空间减少)。考虑到Arrays类仅用于这一个循环这一事实。更改足够小,不会降低clear方法的可读性HashMap
我的意见是,这可以被认为是一种改进,即使只是偶然的 对我来说,原因可能是性能的提高,而代码清晰度方面的成本可以忽略不计 请注意,
fill
方法的实现非常简单,它是一个将每个数组元素设置为null的简单for循环。因此,用实际实现替换对它的调用不会导致调用方方法的清晰性/简洁性的任何显著降低
P>潜在的绩效收益并不是那么微不足道的,如果你考虑所有涉及的事情:
数组
类,也不需要在需要时加载和初始化它。这是一个非常重要的过程,JVM执行几个步骤。首先,它检查类加载器以查看类是否已经加载,并且每次调用方法时都会发生这种情况;当然,这里涉及到一些优化,但仍然需要一些努力。如果未加载该类,JVM将需要经历昂贵的加载过程,验证字节码,解决其他必要的依赖关系,最后执行该类的静态初始化(这可能是任意昂贵的)。鉴于HashMap
是一个如此核心的类,而Arrays
是一个如此庞大的类(3600多行),避免这些成本可能会带来显著的节约Arrays.fill(…)
方法调用,JVM不必决定是否/何时将方法内联到调用方的主体中。由于HashMap#clear()
经常被调用,JVM最终将执行内联,这需要JIT重新编译clear
方法。在没有方法调用的情况下,clear
将始终以最高速度运行(一旦初始JIT)不再在
数组中调用方法的另一个好处是,它简化了java.util
包中的依赖关系图,因为删除了一个依赖关系。我将在这里暗中拍摄
我的猜测是,它可能已被更改,以便为(即泛型而非基本类型)奠定基础。也许(我坚持也许),这一改变是为了在专业化成为JDK的一部分的情况下更容易过渡到Java10
如果您查看,语言限制部分,它会显示以下内容:
由于任何类型变量都可以采用值和引用类型,因此涉及此类类型变量的类型检查规则(此后称为“avars”)。例如,对于avar T:
- 无法将null转换为类型为T的变量
- 无法将T与null进行比较
- 无法将T转换为对象
- 无法将T[]转换为对象[]
(重点是我的)
在前面的专门化转换部分中,它说:
当专门化任何泛型类时,专门化器将执行许多转换,大多数是本地化的,但有些转换需要类或方法的全局视图,包括:
- 对所有方法的签名执行类型变量替换和名称篡改
随后,在文件末尾的进一步调查部分,它说:
虽然我们的实验已经证明,以这种方式进行专门化是可行的,但还需要进行更多的研究。具体来说,我们需要针对任何核心JDK库,特别是集合和流,执行一些有针对性的实验
现在,关于变化
如果将专门化Arrays.fill(Object[]array,Object value)
方法,则其签名应更改为Arrays.fill(
public void clear() {
modCount++;
Arrays.fill(table, null);
size = 0;
}
public void clear() {
Node<K,V>[] tab;
modCount++;
if ((tab = table) != null && size > 0) {
size = 0;
for (int i = 0; i < tab.length; ++i)
tab[i] = null;
}
}
public class HashMapTest {
public static void main(String[] args) {
new java.util.HashMap();
}
}
... 155 lines skipped ...
[Loaded java.util.Set from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.AbstractSet from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$EmptySet from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$EmptyList from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$EmptyMap from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$UnmodifiableCollection from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$UnmodifiableList from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.Collections$UnmodifiableRandomAccessList from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.Reflection from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
**[Loaded java.util.HashMap from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.HashMap$Node from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.Class$3 from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.Class$ReflectionData from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.Class$Atomic from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.generics.repository.AbstractRepository from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.generics.repository.GenericDeclRepository from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.generics.repository.ClassRepository from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.Class$AnnotationData from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.annotation.AnnotationType from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.util.WeakHashMap from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.ClassValue$ClassValueMap from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.reflect.Modifier from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded sun.reflect.LangReflectAccess from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
[Loaded java.lang.reflect.ReflectAccess from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
**[Loaded java.util.Arrays from C:\Program Files\Java\jre1.8.0_60\lib\rt.jar]
...
36 3 java.util.WeakHashMap::clear (50 bytes)
!m @ 4 java.lang.ref.ReferenceQueue::poll (28 bytes)
@ 17 java.lang.ref.ReferenceQueue::reallyPoll (66 bytes) callee is too large
@ 28 java.util.Arrays::fill (21 bytes)
!m @ 40 java.lang.ref.ReferenceQueue::poll (28 bytes)
@ 17 java.lang.ref.ReferenceQueue::reallyPoll (66 bytes) callee is too large
@ 1 java.util.AbstractMap::<init> (5 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 9 java.lang.ref.ReferenceQueue::<init> (27 bytes) inline (hot)
@ 1 java.lang.Object::<init> (1 bytes) inline (hot)
@ 10 java.lang.ref.ReferenceQueue$Lock::<init> (5 bytes) unloaded signature classes
@ 62 java.lang.Float::isNaN (12 bytes) inline (hot)
@ 112 java.util.WeakHashMap::newTable (8 bytes) inline (hot)
void jdk7clear() {
Arrays.fill(table, null);
}
void jdk8clear() {
Object[] tab;
if ((tab = table) != null) {
for (int i = 0; i < tab.length; ++i)
tab[i] = null;
}
}
Map size | JDK 7 (sd)| JDK 8 (sd)| JDK 8 vs 7
16| 2267 (36)| 1521 (22)| 67%
64| 3781 (63)| 1434 ( 8)| 38%
256| 3092 (72)| 1620 (24)| 52%
1024| 4009 (38)| 2182 (19)| 54%
4096| 8622 (11)| 4732 (26)| 55%
16384| 27478 ( 7)| 12186 ( 8)| 44%
65536| 104587 ( 9)| 46158 ( 6)| 44%
262144| 445302 ( 7)| 183970 ( 8)| 41%
Map size | JDK 7 (sd)| JDK 8 (sd)| JDK 8 vs 7
16| 75 (15)| 65 (10)| 87%
64| 116 (34)| 90 (15)| 78%
256| 246 (36)| 191 (20)| 78%
1024| 751 (40)| 562 (20)| 75%
4096| 2857 (44)| 2105 (21)| 74%
16384| 13086 (51)| 8837 (19)| 68%
65536| 52940 (53)| 36080 (16)| 68%
262144| 225727 (48)| 155981 (12)| 69%