如何低效率传递Collections.unmodifiable *一个实例,已经包装了Collections.unmodifiable *? [英] How inefficient is passing Collections.unmodifiable* an instance which is already wrapped with Collections.unmodifiable*?

查看:143
本文介绍了如何低效率传递Collections.unmodifiable *一个实例,已经包装了Collections.unmodifiable *?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些片段是通过不同的定制(源代码不可用)框架来完成的,这些框架会传递Map实例。不幸的是,这些框架在返回的Map实例中是不一致的,这些实例被Collections.unmodifiableMap包装。为了确保更高程度的不可变性(为了更容易的多线程使用)在我的代码,我已经统一调用Collections.unmodifiableMap这些框架返回的任何东西。

  Map< String,Record> immutableMap = framework.getRecordsByName(); 
//这是否创建了一个嵌套的unmodifiableMap包装器实例集?
this.immutableField = Collections.unmodifiableMap(immutableMap);



Map< String,Record> maybeImmutableMap = framework.getRecordsByName();
//有一些方法来获取instanceof工作?
if(!(maybeImmutableMap instanceof Collections.UnmodifiableMap))
{
this.immutableField = Collections.unmodifiableMap(maybeImmutableMap);
}

我意识到我可能在我的设计的这一部分有一个性能问题。在某些情况下,我调用Collections.unmodifiableMap传递一个实例,该实例已被框架通过相同的调用包装。而且我的重新包装很可能导致在整个实例上调用一个额外的方法。



似乎使用instanceof Collections.UnmodifiableMap不工作。我不能找到任何方法来检测(不包括使用反射这不是一个选项在这种情况下 - 方法太慢)如果我正在引用的Map实例需要包装或不包装。



问题:

    A)Collections.unmodifiableMap()方法检查是否传递了UnmodifiableMap的一个实例,如果是,相同的引用(从而避免在调用方法之前检查)?



    B)为了主动避免接收修改异常,是否有一种查询映射实例(不是使用反射)来检测它是否是可变的(或不可变的)?



    C)如果A的答案是否定的, JVM / HotSpot,消除了通过多个方法跳转到核心实例的开销。


解决方案

反馈,我得出结论,无论我做什么,解决方案将是一些形式的kludge(有温和的气味)。我认为这是由于收集API生成不可修改的实例的部分没有提供避免嵌套不可修改的实例,也没有提供一个公共的方式,客户端正确地避免嵌套。



由于考虑到多个类加载器和通过RMI的序列化,我真正喜欢的一个解决方案(Jorn Horstmann的类参考比较)有问题。但是,当我采取他的方法,并结合类名方法(由Eugene Kuleshov推荐)的修改,我想我得到尽可能接近,我会得到一个解决方案,将帮助我在我的多线程分布式处理环境。它有点像这样:

  public class MyCollections {
private static final String UNMODIFIABLE_MAP_CLASS_NAME =
Collections.unmodifiableMap(new HashMap())。getClass()。getName();

public static< K,V>地图< K,V> unmodifiableMap(Map< K,V> map){
return map.getClass()。getName()。equals(UNMODIFIABLE_MAP_CLASS_NAME)
? map
:Collections.unmodifiableMap(map);
}
}

这仍然具有参考比较的所有优点假设一切都发生在同一个ClassLoader上下文中,类名的字符串已正确嵌入。它做它,而礼貌地保持封装(避免我的代码直接引用类名)。然而,如果两个假设不成立,那么评估将回到标准字符串比较,假设类名不在库的不同版本之间改变(似乎具有相当低的概率)。 / p>

在这种方法中,我忘记了或遗漏了什么?



再次感谢大家反馈。我真的很感激。


I have bits of piecework being done by different custom (source code unavailable) frameworks which hand back Map instances. Unfortunately, these frameworks are not consistent in their returning Map instances which have been wrapped with Collections.unmodifiableMap. To ensure a higher degree of immutability (for easier multi-threaded use) in my code, I have just uniformly called Collections.unmodifiableMap on anything returned by these frameworks.

Map<String, Record> immutableMap = framework.getRecordsByName();
//does this created a nested set of unmodifiableMap wrapper instances?
this.immutableField = Collections.unmodifiableMap(immutableMap);
.
.
.
Map<String, Record> maybeImmutableMap = framework.getRecordsByName();
//is there some means to get instanceof to work?
if (!(maybeImmutableMap instanceof Collections.UnmodifiableMap))
{
    this.immutableField = Collections.unmodifiableMap(maybeImmutableMap);
}

I realized that I might have a performance issue around this part of my design. And that in some instances, I was calling Collections.unmodifiableMap passing it an instance which had already been wrapped by the framework by the same call. And that my re-wrapping was likely causing an extra method call across the entire instance.

It appears that using "instanceof Collections.UnmodifiableMap" doesn't work. And I cannot find any way to detect (excluding using reflection which is not an option in this situation - WAY too slow) if the Map instance I am currently referencing needs to be wrapped or not.

Questions:

    A) Does the Collections.unmodifiableMap() method check to see if it was passed an instance of UnmodifiableMap, and if so just return the same reference (thereby avoiding the need to check prior to calling the method)?

    B) In order to proactively avoid receiving modification exceptions, is there a way to query a Map instance (other than using reflection) to detect if it is mutable (or immutable)?

    C) If the answer to A is no, then is there some efficiencies in the JVM/HotSpot which eliminate the overhead of calling through the multiple method hops to get to the core instance?

解决方案

After reviewing all of the feedback, I came to the conclusion that no matter what I do, the solution is going to be some form of kludge (have a mild odor). I think this is due to the fact that the part of the Collections API which produces unmodifiable instances didn't provide for avoiding nesting unmodifiable instances nor did it provide a "public" way for a client to properly avoid the nesting.

And due to considerations around multiple class loaders and serialization via RMI, the one solution I really liked (class reference comparison by Jorn Horstmann) has issues. However, when I take his approach and combine it with a modification of the class name approach (recommneded by Eugene Kuleshov), I think I get as close as I am going to get to having a solution that will help me in my multi-threaded distributed processing environment. And it goes a little bit like this:

public class MyCollections {
    private static final String UNMODIFIABLE_MAP_CLASS_NAME =
        Collections.unmodifiableMap(new HashMap()).getClass().getName();

    public static <K, V> Map<K, V> unmodifiableMap(Map<K, V> map) {
        return map.getClass().getName().equals(UNMODIFIABLE_MAP_CLASS_NAME)
                 ? map
                 : Collections.unmodifiableMap(map);
    }
}

This will still has all the advantages of a reference comparison assuming everything is happening within the same ClassLoader context and the classname's string has been properly interned. And it does it while politely keeping encapsulation (avoiding my code referencing the class name directly). However, if the two assumptions don't hold, then the evaluation will fall back to a standard string comparison which will work assuming the class name does not change between different versions of the library (which seems to have a pretty low probability).

Is there anything I am forgetting or missing in this approach?

And thank you again, everyone, for your feedback. I really appreciate it.

这篇关于如何低效率传递Collections.unmodifiable *一个实例,已经包装了Collections.unmodifiable *?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆