为什么 HashMap 不能有不同的 NaN 值作为键?

Veg*_*ard 2 java hashmap data-structures

import java.util.*;

public class MyClass {
    public static void main(String args[]) {
      Map<Float, Integer> m = new HashMap<>();
      
      m.put(Float.intBitsToFloat(0x7f800001), 1);
      m.put(Float.intBitsToFloat(0x7f800002), 2);
      
      System.out.println(m.size());
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么上面的代码返回的1大小是m0x7f8000010x7f800002都是 NaN 浮点值,但根据NaN != NaN定义,这不应导致冲突。

该行为类似于nullJava Hashmap 中记录的键处理,但我找不到任何表明该处理NaN是由 HashMap 处理的内容null

Jon*_*eet 7

Float.equals(Object)记录为:

将此对象与指定对象进行比较。当且仅当参数不为 null 并且是Float表示浮点数的对象且其值与该对象所表示的浮点数相同时,结果才为 true。为此,当且仅当该方法在应用于每个浮点值时floatToIntBits(float) 返回相同的值时,两个浮点值才被视为相同。int

现在听起来不同的 NaN 值应该被视为不相等,但floatToIntBits文档包括(强调我的):

如果参数为 NaN,则结果为 0x7fc00000。

在所有情况下,结果都是一个整数,当给该intBitsToFloat(int)方法时,将生成一个与参数相同的浮点值floatToIntBits (除了所有 NaN 值都折叠为单个“规范”NaN 值)

所以基本上,Float.equals(and Float.hashCode,也使用floatToIntBits(float)) 将所有 NaN 值视为相等。