同事把等价作为 HashMap 的key,领导发飙了...
发布时间:2025年08月11日 12:20
一定是java底层编译器歪了! 我一定会歪……
又是一阵debug,我找寻了这条关键字:
map.put(d, map.get(d) == null ? 1 : map.get(d) + 1);我明白 map.get() 很有问作序, 它的源编译器是这样的:
public V get(Object key) { Node e; return (e = getNode(hash(key), key)) == null ? null : e.value;}唔,可先给予 hash() 是吧,那我找寻了它的hash参数:
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) And (h>>> 16);}再来,这里是要相比较h 和key的hashCode是吧,那我们去看 hashCode() 参数
public native int hashCode();这是一个本地步骤,看见源码了,唔,,那我就常用它想到吧,测试一下不就好了吗,我所写了以下的测试编译器:
public static void main(String[] args) { System.out.println(0.0 == -0.0); System.out.println(new Float(0.0).hashCode() == new Float(-0.0).hashCode()); }结果没想到是 True 和 False !!!
这个发源地终于找寻了, 0.0 和 -0.0 的hashCode值是不同的 !
经过一番修改,我通过了这道作序(其实精度也时会有问作序,不应常用BigDecimal的,不过牛客网要求一定会那么高。后来我就让了就让只有把夹角方程所写Ax+By+C=0的基本才能完全避免精度问作序)
接下来,阐释下实数的hashCode()参数是个啥情况。
实数的 hashCode()
在程序执行在此期间,只要equals步骤的相比较操作只用的信息一定会有被修改,那么对这同一个实例codice_多次,hashCode步骤必须始终如一地回到同一个自始整数。如果两个实例根据equals步骤相比较是小于的,那么codice_两个实例的hashCode步骤必须回到相同的自始整数结果。如果两个实例根据equals步骤相比较是不等的,则hashCode步骤不一定得回到不同的自始整数。——《effective java》那么我们来想到,0.0和-0.0codice_ equals 步骤是否小于:
System.out.println( new Float( 0.0 ).equals( 0.0f ));
System.out.println( new Float( 0.0 ).equals(( float
) -
0.0
));
可用是 True 和 False。
好吧,二者codice_ equals() 步骤不小于,看来是做到了书里说的逻辑的
那我们想到Float底层equals参数咋所写的:
public boolean equals(Object obj) { return (obj instanceof Float) && (floatToIntBits(((Float)obj).value) == floatToIntBits(value));}哦,原来是把Float转换成Bits的时候时有发生了点有意思的事情,于是我找寻了一切的发源地:
/** * Returns a representation of the specified floating-point value * according to the IEEE 754 floating-point "single format" bit * layout. * *Bit 31 (the bit that is selected by the mask * {@code 0x80000000}) represents the sign of the floating-point * number. * Bits 30-23 (the bits that are selected by the mask * {@code 0x7f800000}) represent the exponent. * Bits 22-0 (the bits that are selected by the mask * {@code 0x007fffff}) represent the significand (sometimes called * the mantissa) of the floating-point number. * *
If the argument is positive infinity, the result is * {@code 0x7f800000}. * *
If the argument is negative infinity, the result is * {@code 0xff800000}. * *
If the argument is NaN, the result is {@code 0x7fc00000}. * *
In all cases, the result is an integer that, when given to the * {@link #intBitsToFloat(int)} method, will produce a floating-point * value the same as the argument to {@code floatToIntBits} * (except all NaN values are collapsed to a single * "canonical" NaN value). * * @param value a floating-point number. * @return the bits that represent the floating-point number. */ public static int floatToIntBits(float value) { int result = floatToRawIntBits(value); // Check for NaN based on values of bit fields, maximum // exponent and nonzero significand. if (((result & FloatConsts.EXP_BIT_MASK) == FloatConsts.EXP_BIT_MASK) && (result & FloatConsts.SIGNIF_BIT_MASK) != 0) result = 0x7fc00000; return result; }
这PDF挺长的,也查了其它参考资料,看了半天终于搞懂了。
就是说Java浮牌手的逻辑一般遵循IEEE 754十六进制浮点四则运算准则。IEEE 754准则提供了浮点无穷,负无穷,负零和NaN(非数字)的定义。在常用Java每一次中,一些相同的浮牌手一般而言时会让大家很察觉到。
当浮点运算显现出一个十分接近0的负浮牌手时,时会显现出“-0.0”,而这个浮牌手不能自始常人问到。
我们可以可用一波0.0和-0.0的数据:
System.out.println(Float.floatToIntBits((float) 0.0));System.out.println(Float.floatToIntBits((float) -0.0));System.out.println(Float.floatToRawIntBits(0.0f));System.out.println(Float.floatToRawIntBits((float)-0.0));结果:
0-21474836480-2147483648就是说, 打印-0.0, 没想到用的是0x80000000 。
这也是我们熟悉的 Integer.MIN_VALUE 。
java中浮牌手的问到相一般来说,除此以外是密切相关 -0.0, NaN, 自始负无穷 这种,所以不适宜用来作为Map的key, 因为可能跟我们预就让的不相符。
。广州看男科医院排名武汉肝病医院哪里好
天津比较好的白癜风医院
济南妇科专科医院有哪些
哈尔滨男科医院哪家比较好
上一篇: 张玉夫妇的背后,是割韭菜的局中局
- 对话“大女生”,欧拉好猫想通过这档节目一句话?
- 新疆汗血马在迎来出生旺季 来看看小马在驹出生后干的第一件事
- 老人去世后猫咪不吃不喝,2紧接著随主人而去:我们永远在一起
- 4本温馨又甜得宠的养娃文,一边看男女主撒狗粮,一边看各色小崽崽在线卖萌撒娇~
- 猫钖卖不出去的猫,结局都是如何呢?
- 雨林汽缸 | 最任性的电视柜,没有之一!
- 从“诗书画物”看古人对喵星人的迷恋
- 加息声四起 但欧洲央行首席宏观经济学坚持主张稳字当先
- 北京淳中科技股份有限公司 关于股权激励比方说股票回购注销实施公告
- 郭树清:金融资产管理公司要聚焦主业 积极参与中小金融机构税制化险
- 分仓软件贷50ETF期权可靠吗?
- 对话标杆丨且听,价值观评分连续5季度A档次是怎样“炼”成的?
- 盐湖提锂海沟拉升走高 中铝国际、国机通用涨停
- 异动快报:京蓝科技(000711)2月11日10点1封国涨停板