简体   繁体   English

当long值传递给get方法时,使用整数作为键的映射返回null

[英]Map with integer as key returns null when long value is passed to the get method

import java.util.HashMap;
import java.util.Map;

public class StackOverFlowQuestion {

private static final int ERROR_CODE100 = -100;
private static final int ERROR_CODE101 = -101;
private static final int ERROR_CODE102 = -102;
private static final int ERROR_CODE103 = -103;
private static final int ERROR_CODE104 = -104;

public enum ErrorDetails {

    ERROR_CODE_100(ERROR_CODE100, "Error code 100 Desc", false),

    ERROR_CODE_101(ERROR_CODE101, "Error code 101 Desc", false),

    ERROR_CODE_102(ERROR_CODE102, "Error code 102 Desc", true),

    ERROR_CODE_103(ERROR_CODE103, "Error code 103 Desc", false),

    ERROR_CODE_104(ERROR_CODE104, "Error code 104 Desc", true);

    private int errorCode;
    private String errorMsg;
    private boolean canRetry;

    private ErrorDetails(int errorCode, String errorMsg, boolean canRetry) {
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        this.canRetry = canRetry;
    }

    public String getErrorMsg() {
        return this.errorMsg;
    }

    public boolean canRetry() {
        return this.canRetry;
    }

    public String toString() {
        return "Error code : " + errorCode + ", errorMsg : " + errorMsg
                + ", canRetry : " + canRetry;
    }
}

private Map<Integer, ErrorDetails> errorMap;

public StackOverFlowQuestion() {
    System.out.println("StackOverFlowQuestion.StackOverFlowQuestion()");

    errorMap = new HashMap<Integer, StackOverFlowQuestion.ErrorDetails>();

    errorMap.put(ERROR_CODE100, ErrorDetails.ERROR_CODE_100);
    errorMap.put(ERROR_CODE101, ErrorDetails.ERROR_CODE_101);
    errorMap.put(ERROR_CODE102, ErrorDetails.ERROR_CODE_102);
    errorMap.put(ERROR_CODE103, ErrorDetails.ERROR_CODE_103);
    errorMap.put(ERROR_CODE104, ErrorDetails.ERROR_CODE_104);

    System.out.println("errorMap : " + errorMap);
}

/**
 * @param args
 */
public static void main(String[] args) {
    long param = -100;
    StackOverFlowQuestion question = new StackOverFlowQuestion();
    System.out.println("question.errorMap : " + question.errorMap);

    System.out.println("question.errorMap.containskey(param) : "
            + question.errorMap.containsKey(param));
    ErrorDetails errorDetails = question.errorMap.get(param);
    System.out.println("errorDetails : " + errorDetails);

    System.out.println("question.errorMap.containskey((int)param) : "
            + question.errorMap.containsKey((int) param));
    ErrorDetails errorDetailsWithInt = question.errorMap.get((int) param);
    System.out.println("errorDetailsWithInt : " + errorDetailsWithInt);

            int paramInt = -100;
    System.out.println("param == paramInt : " + (param == paramInt));
}

} }

================================================================================= Output: ================================================== ===============================输出:

StackOverFlowQuestion.StackOverFlowQuestion()

errorMap : {-100=Error code : -100, errorMsg : Error code 100 Desc, canRetry : false, -102=Error code : -102, errorMsg : Error code 102 Desc, canRetry : true, -101=Error code : -101, errorMsg : Error code 101 Desc, canRetry : false, -104=Error code : -104, errorMsg : Error code 104 Desc, canRetry : true, -103=Error code : -103, errorMsg : Error code 103 Desc, canRetry : false}

question.errorMap : {-100=Error code : -100, errorMsg : Error code 100 Desc, canRetry : false, -102=Error code : -102, errorMsg : Error code 102 Desc, canRetry : true, -101=Error code : -101, errorMsg : Error code 101 Desc, canRetry : false, -104=Error code : -104, errorMsg : Error code 104 Desc, canRetry : true, -103=Error code : -103, errorMsg : Error code 103 Desc, canRetry : false}

question.errorMap.containskey(param) : false
errorDetails : null

question.errorMap.containskey((int)param) : true
errorDetailsWithInt : Error code : -100, errorMsg : Error code 100 Desc, canRetry : false

param == paramInt : true

================================================================================= ================================================== ===============================

Here are few question which I need clarification 这里有几个我需要澄清的问题

  1. The code is compiling even if I pass a long as the parameter to the get method of the HashMap which is declared to have only Integer as the keys. 代码正在编译,即使我将一个long作为参数传递给HashMap的get方法,该方法被声明为只有Integer作为键。 I was expecting a compilation error here, because I somehow feel this violates the strict typing. 我在这里期待编译错误,因为我不知何故觉得这违反了严格的打字。
  2. When I pass the long variable containing the error code as the parameter to the get method of the HashMap() the map returns null. 当我将包含错误代码的long变量作为参数传递给HashMap()的get方法时,映射返回null。
  3. When I downcast the same long parameter to an int and pass it to the get method of the hash map, the map returns the proper Enum. 当我将相同的long参数向下转换为int并将其传递给哈希映射的get方法时,映射将返回正确的Enum。

I suspect the below line in the HashMap.get() method if (e.hash == hash && ((k = e.key) == key || key.equals(k))) 我怀疑if (e.hash == hash && ((k = e.key) == key || key.equals(k))) ()方法中的if (e.hash == hash && ((k = e.key) == key || key.equals(k)))if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

I am not sure whether int == long will fail or their corresponding wrappers will fail., i even added a check in the main method to verify the equality of the int and long variables. 我不确定int == long是否会失败或者它们相应的包装器是否会失败。我甚至在main方法中添加了一个检查以验证int和long变量的相等性。

I would like to understand the behavior here. 我想了解这里的行为。

The code is compiling even if I pass a long as the parameter to the get method of the HashMap which is declared to have only Integer as the keys. 代码正在编译,即使我将一个long作为参数传递给HashMap的get方法,该方法被声明为只有Integer作为键。 I was expecting a compilation error here, because I somehow feel this violates the strict typing. 我在这里期待编译错误,因为我不知何故觉得这违反了严格的打字。

Did you look at the signature of Map.get ? 你看过Map.get的签名了吗?

V get(Object key)

Any object can be used as the key. 任何对象都可以用作密钥。 There are other Stack Overflow questions about that design decision; 关于该设计决策还有其他Stack Overflow问题; I'll find one later. 我稍后会找到一个。

When I pass the long variable containing the error code as the parameter to the get method of the HashMap() the map returns null. 当我将包含错误代码的long变量作为参数传递给HashMap()的get方法时,映射返回null。

Yes, it would - because it will be boxed to a Long , and a Long isn't equal to an Integer . 是的,它会 - 因为它将被装箱为Long ,而Long不等于Integer So the entry isn't found in the map. 因此,在地图中找不到该条目。

When I downcast the same long parameter to an int and pass it to the get method of the hash map, the map returns the proper Enum. 当我将相同的long参数向下转换为int并将其传递给哈希映射的get方法时,映射将返回正确的Enum。

Yes, it would - because then it will be boxed to an Integer , which will be equal to the appropriate key. 是的,它会 - 因为它将被装箱到一个Integer ,它将等于相应的密钥。

Basically you're being fooled by the fact that you can compare int and long values - that's just the compiler automatically promoting int to long for you; 基本上你被你可以比较intlong值的事实所欺骗 - 这只是编译器自动提升intlong ; if you think of Integer and Long as entirely separate types, with no automatic conversion between them, the behaviour of your map makes perfect sense. 如果你认为IntegerLong是完全独立的类型,它们之间没有自动转换,那么地图的行为就非常有意义了。

1.) The code is compiling even if I pass a long as the parameter to the get method of the HashMap which is declared to have only Integer as the keys. 1.)代码正在编译,即使我将一个long作为参数传递给HashMap的get方法,该方法被声明为只有Integer作为键。 I was expecting a compilation error here, because I somehow feel this violates the strict typing. 我在这里期待编译错误,因为我不知何故觉得这违反了严格的打字。

No compilation error here: the only methods of Map with parameters bounded by the generic types are the put methods. 这里没有编译错误:使用泛型类型限制的参数的唯一Map方法是put方法。 get and containsKey accept an Object . getcontainsKey接受一个Object

2.) When I pass the long variable containing the error code as the parameter to the get method of the HashMap() the map returns null. 2.)当我将包含错误代码的long变量作为参数传递给HashMap()的get方法时,映射返回null。

When you invoke get(param) it gets translated into get(new Long(param)) . 当你调用get(param)它会被转换为get(new Long(param)) So the argument never equals the Integer keys 因此参数永远不会等于Integer

3.) When I downcast the same long parameter to an int and pass it to the get method of the hash map, the map returns the proper Enum. 3.)当我将相同的long参数向下转换为int并将其传递给哈希映射的get方法时,映射将返回正确的Enum。

When you invoke get((int)param) it gets translated into get(new Integer((int)param)) . 当你调用get((int)param)它会被转换为get(new Integer((int)param)) So the argument type is now correct, and the result is the one you expected. 所以参数类型现在是正确的,结果是你期望的结果。

你需要将long转换为int。

The short answer is: Integer == Long will always fail to be equal ([Long].equal([Integer]) == false) nor might Long.hashCode() == Integer.hashCode() return the same result. 简短的回答是: Integer == Long总是不能相等([Long] .equal([Integer])== false)也不会Long.hashCode()== Integer.hashCode()返回相同的结果。

To elaborate on that answer: 详细说明答案:

Because of Autoboxing your long will be converted into a Long, which will then be compared to any other Object with the same hashCode within the Map. 由于Autoboxing,您的long将被转换为Long,然后将其与Map中具有相同hashCode的任何其他Object进行比较。 Since the specific implementation of HashCode must not be equal for Long & Integer, that might already fail. 由于HashCode的具体实现不能等于Long&Integer,因此可能已经失败。 If the hashCodes are the same though there is the equals check to be done, which will fail because like every equals method out there checks for "is instance of [Type]" or returns false. 如果hashCodes是相同的,虽然有等待检查要完成,这将失败,因为像每个equals方法那样检查“是[Type]的实例”或返回false。 Which will fail in every case of comparing a Long to an Integer. 在将Long与Integer进行比较的每种情况下都会失败。

So all you need to do in your case is cast you long to an int or do Integer.valueOf((int)param) which will do exactly the same (autoboxing). 因此,在你的情况下你需要做的就是将你长时间转换为int或者做Integer.valueOf((int)param),这将完全相同(autoboxing)。

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

相关问题 使用方法中传递的参数从 Map 获取一对键+值 - Get a pair key+value from a Map with a parameter passed in a method 传递给需要对象类型的方法时,整数变为长整数 - Integer becomes Long when passed to the method that is expecting a Object Type Hashmap get(key)即使存在该值也返回null - Hashmap get(key) returns null even when the value is present TreeMap键,值对存在,但.get(Key)返回该值为null - TreeMap Key, Value pair exists, but .get(Key) returns the value as null JdbcTemplate.queryforList()返回值,但map.get返回null - JdbcTemplate.queryforList() returns value but map.get returns null 将值传递给Action类方法时,变量值将为null - variable value is taking as null when the value is passed to the Action class method 从单独的方法调用时,getKey(alias, keyPassword) 返回密钥的 null 值 - getKey(alias, keyPassword) returns null value for secret key when calling from separate method 哈希图中的JSTL访问整数/长键 - JSTL Access Integer/Long key in Hash Map 来自模拟 ModelMapper 的 map() 方法返回 null 值 - map() method from mocked ModelMapper returns null value 哈希图 <Node, Integer> 即使hashcode()相同,get也会返回null - HashMap<Node, Integer> get returns null even when hashcode() is the same
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM