简体   繁体   English

为什么两个具有相同值的原始双精度具有两个不同的identityHashCode?

[英]why two primitive doubles with same value have two different identityHashCode?

I learned that all primitives with same value have same identityHashCode so, I wanted get identityHashCode of some primitives.so when I tried with 2 doubles with same value it was giving different identityHashCode I did following: 我了解到,与相同值的元都有相同identityHashCode所以,我希望得到identityHashCode一些primitives.so的,当我和2个双打这是给不同的值相同试图identityHashCode我没有以下内容:

int xInt=5;
int yInt=5;

System.out.println(System.identityHashCode(xInt));//output:1867083167
System.out.println(System.identityHashCode(yInt));//output:1867083167

double double1=5;
double double2=5;


System.out.println(System.identityHashCode(double1));//output:1915910607

System.out.println(System.identityHashCode(double2));//output:1284720968

two ints with same value have same identityHashCode but two doubles with same value have different identityHashCode why is that? 两个具有相同值的int具有相同的identityHashCode但是两个具有相同值的双精度具有不同的identityHashCode为什么会这样?

Your code is boxing the primitive values. 你的代码正在装箱原始值。 (The primitive values themselves don't have an identity hash code, as that's only a concept that's relevant for objects.) Your code is equivalent to this: (原始值本身没有标识哈希码,因为这只是与对象相关的概念。)您的代码等同于:

int xInt=5;
int yInt=5;

Integer xInteger = xInt;
Integer yInteger = yInt;

System.out.println(System.identityHashCode(xInteger));
System.out.println(System.identityHashCode(yInteger));

double double1=5;
double double2=5;

Double boxedDouble1 = double1;
Double boxedDouble2 = double2;

System.out.println(System.identityHashCode(boxedDouble1));
System.out.println(System.identityHashCode(boxedDouble2));

Now if you compare the references themselves, you'll see that xInteger == yInteger is true, but boxedDouble1 == boxedDouble2 is false... so identityHashCode is representing that relationship accurately. 现在,如果您比较引用本身,您将看到xInteger == yInteger为true,但boxedDouble1 == boxedDouble2为false ...因此identityHashCode正确表示该关系。

The reason your boxed integer references refer to the same object is that boxed integral types within a particular range are cached : 您的盒装整数引用引用同一对象的原因是缓存特定范围内的盒装整数类型

If the value p being boxed is the result of evaluating a constant expression (§15.28) of type boolean, char, short, int, or long, and the result is true, false, a character in the range '\' to '\' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. 如果装箱的值p是评估boolean,char,short,int或long类型的常量表达式(第15.28节)的结果,结果为true,false,则为'\\ u0000'到''范围内的字符\\ u007f'包含,或-128到127(含)范围内的整数,然后让a和b为p的任意两次装箱转换的结果。 It is always the case that a == b. a == b总是如此。

The range can actually be bigger in practice, and an implementation could cache boxed doubles as well, but I haven't seen that happen. 在实践中,范围实际上可能更大,并且实现也可以缓存盒装双打,但我还没有看到这种情况发生。

i learned that all primitives with same value have same identityHashCode 我了解到所有具有相同值的基元具有相同的identityHashCode

That can't be true, since primitives, by definition, are not objects, and thus don't have an identity hash code in the first place. 这不可能是真的,因为根据定义,原语不是对象,因此首先没有标识哈希码。

When you're calling System.identityHashCode() , the argument is boxed to an Integer or a Double. 当您调用System.identityHashCode() ,参数将被装箱为Integer或Double。

And Integer boxing uses a cache for the frequently used integers (from -128 to 127 by default). 并且整数装箱使用常用整数的缓存 (默认情况下从-128到127)。 That's not the case for Double boxing. 双拳并非如此。

Try it with a large int, and you'll get different results, too. 尝试使用大型int,你也会得到不同的结果。

There's a boxing issue at play here - you can't compare primitive datatypes with identityHashCode as it uses Object as its parameter. 这里有一个拳击问题 - 您无法将原始数据类型与identityHashCode进行比较,因为它使用Object作为其参数。

Returns the same hash code for the given object as would be returned by the default method hashCode() 返回与默认方法hashCode()返回的给定对象相同的哈希码

But of course double isn't the same as Double . 但当然doubleDouble

i learned that all primitives with same value have same identityHashCode. 我了解到所有具有相同值的基元具有相同的identityHashCode。

There are at least two misconceptions there. 那里至少存在两种​​误解。 First, primitives don't have hash codes or identity hash codes at all . 首先, 原始数据没有哈希代码或标识哈希代码在所有 It is Objects that do, such as the wrapper objects obtained by autoboxing primitive values. 它是对象 ,例如通过自动装箱原始值获得的包装器对象。

Second, the overall idea is simply wrong, as your own experiment demonstrates. 其次,总体思路完全错误,正如您自己的实验所证明的那样。 If you provide a primitive as the argument to System.identityHashCode() then it is autoboxed into an instance of the appropriate wrapper class, and the identity hash code of the resulting object is returned. 如果您提供一个原语作为System.identityHashCode()的参数,那么它将被自动装箱到相应包装类的实例中,并返回结果对象的标识哈希码。 An object's identity hash code is uniquely characteristic of that object during its lifetime, and independent of its state. 对象的标识哈希码在其生命周期中是该对象的唯一特征,并且与其状态无关。 No two objects existing at the same time have the same identity hash code. 同时存在的两个对象不具有相同的标识哈希码。 What's more interesting, then, is not that you get different identity hash codes for the autoboxed double s, but that you get the same identity hash codes for autoboxed small integers. 那么,更有趣的是,你不是为自动装箱的double s获得不同的身份哈希码,而是为自动装箱的小整数获得相同的身份哈希码。

In fact, this shows that Java maintains a cache of Integer objects for small integer values. 实际上,这表明Java为小整数值维护了Integer对象的缓存。 It uses these when autoboxing values in the range covered, and when handling explicit Integer.valueOf() invocations for those values. 它在覆盖范围内的自动装箱值时以及处理这些值的显式Integer.valueOf()调用时使用这些值。 Thus, in your example, you get the same object each time you autobox the integer 5, and you see the same identity hash code. 因此,在您的示例中,每次自动装订整数5时都会获得相同的对象,并且您会看到相同的标识哈希码。 If you used a sufficiently large value then you would not see the same effect. 如果您使用了足够大的值,那么您将看不到相同的效果。

Java does not perform such caching for the Double s with value 5.0. Java不会为值为5.0的Double s执行此类缓存。

On the other hand, perhaps you simply misunderstood the lesson. 另一方面,也许你只是误解了这一课。 Distinct wrapper objects representing the same primitive type and value don't have the same identity hash code, but they do have the same (regular) hash code, because that, for the wrapper classes, is determined by the primitive values they represent. 表示相同的基本类型和值不同的包装对象不具有相同身份的散列码,但它们确实具有相同的(常规)散列码,因为,对于包装类,由它们所表示的原始值来确定。 So compare the results of your code to the results of this: 因此,将代码的结果与此结果进行比较:

    System.out.println(Double.valueOf(double1).hashCode());
    System.out.println(Double.valueOf(double2).hashCode());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以假设具有相同 System.identityHashCode 的两个对象是相同的吗? - Can I assume two objects with the same System.identityHashCode are the same? 确定两个Doubles数组是否具有相同顺序的元素? - Determine if two arrays of Doubles have their elements in the same order? 为什么具有相同数据的两个不同的 HashSet 具有相同的 HashCode? - Why do two different HashSets with the same data have the same HashCode? Java如何让两个变量指向同一个原始对象 - Java how to have two variables point to the same primitive object 为什么在案例2中对于相同的值有两个不同的答案:在Java 7上? - Why two different answers are coming for the same value in case 2: on Java 7? 为什么加两个双打会给出错误的答案? - Why addition of two doubles is giving wrong answer? 有两个具有相同属性的不同库-Swing - Have two different libraries with same properties - Swing 为什么带签名(primitive,wrapper)和(primitive,primitive)的两个方法会导致方法调用(包装器,原语)不明确? - Why do two methods with signature (primitive, wrapper) and (primitive, primitive) cause the method call (wrapper, primitive) to be ambiguous? 仅当第二个值不为零时才打印两个双精度之间的除法结果 - Printing The Result of a Division Between Two Doubles only if the second value is different from zero 当一个类实现两个接口时,接口具有相同的方法名称,但返回类型不同,为什么它不起作用? - When a class implements two interfaces, interfaces have same method name but different return type why it wont work?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM