什么可以导致HashMap containsKey()以String为键失败?

时间:2011-01-20 14:17:09

标签: java hashmap containskey

我对此深感困惑。我正在运行一整套价值单元测试。以下是许多JUnit测试使用的相关共享代码:

private static Map<String, JAXBContext> jaxbContexts = 
                             new HashMap<String, JAXBContext>();

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException {
    JAXBContext context = null;
    if (jaxbContexts.containsKey(clazz.getName())) {
        context = jaxbContexts.get(clazz.getName());
    } else {
        context = JAXBContext.newInstance(clazz);
        System.out.println("Created new context for '" + clazz.getName() + "'");
        jaxbContexts.put(clazz.getName(), context);
    }
    return context;
}

JUnit运行的控制台输出包括以下两个连续的条目:

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface'

我错过了什么?为什么jaxbContexts.containsKey()在这个实例中不能用于基于String的键,这与JUnit执行期间的其他46次不同?我们并没有并行运行我们的测试,但如果有所不同,我们会使用Aspects。

5 个答案:

答案 0 :(得分:3)

调试它并验证包含此getJAXBContext()方法的类是否仅实例化一次(通过检查它在调试模式下对每次调用都具有相同的内存ID)。如果它是不同的实例,则synchronized关键字将锁定不同的锁,并且它们将使用不同的映射。

答案 1 :(得分:1)

就个人而言,我不会打扰containsKey。

String name = clazz.getName();
context = jaxbContexts.get(name);
if (context == null) {
    context = JAXBContext.newInstance(clazz);
    System.out.println("Created new context for '" + name + "'");
    jaxbContexts.put(name, context);
}

答案 2 :(得分:1)

将包含字符串的Map作为键肯定没有什么特别之处。只需用new Exception().printStackTrace()替换println,你就会看到发生了什么。您可能正在创建包含地图的类的两个实例,或者其他任何内容。

答案 3 :(得分:0)

除了比赛......但是你说你没有并行运行......

无论如何,我会调用context = jaxbContexts.get(clazz.getName())并针对context测试null

啊,并使用类本身作为键,因为多个类可能具有相同的名称(想想类加载器)

答案 4 :(得分:-1)

地图可以是Map<Class, JAXBContext>,而不是Map<String, JAXBContext>,以便于使用。