当前位置: 首页 > 面试题库 >

将Collections.unmodifiable *传递给已经用Collections.unmodifiable *包装的实例,效率低下吗?

翟聪
2023-03-14
问题内容

我通过不同的自定义(源代码不可用)框架来完成一些零碎工作,这些框架将Map实例交还给我。不幸的是,这些框架在返回的Map实例(由Collections.unmodifiableMap包装)中不一致。为了确保我的代码具有更高的不变性(以便更轻松地使用多线程),我对这些框架返回的任何内容统一调用了Collections.unmodifiableMap。

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);
}

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

看来使用“ instanceof
Collections.UnmodifiableMap”无效。而且我找不到任何方法来检测(除非使用反射,在这种情况下这不是一种选择-
方式太慢)是否需要包装当前正在引用的Map实例。

问题:

A)是否可以检查Collections.unmodifiableMap()方法是否传递了UnmodifiableMap的实例,如果是,则返回相同的引用(从而避免在调用该方法之前进行检查)?

B)为了主动避免收到修改异常,是否有一种方法可以查询Map实例(除了使用反射),以检测它是否可变(或不可变)?

C)如果对A的回答为否,那么JVM / HotSpot中是否有一些效率可以消除通过多个方法跃点到达核心实例的调用的开销?


问题答案:

查看所有反馈后,我得出的结论是,无论我做什么,解决方案都将是某种形式的污泥(有轻微的气味)。我认为这是由于这样的事实,即Collections
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> Map<K, V> unmodifiableMap(Map<K, V> map) {
        return map.getClass().getName().equals(UNMODIFIABLE_MAP_CLASS_NAME)
                 ? map
                 : Collections.unmodifiableMap(map);
    }
}

假设 所有事情都在同一个ClassLoader上下文中发生 并且
类名的字符串已正确插入,那么这仍然具有引用比较的所有优点。并且在礼貌地保持封装的同时做到了这一点(避免我的代码直接引用类名)。但是,如果这两个假设不成立,则评估将退回到标准字符串比较,前提是假设类名在库的不同版本之间没有变化(这似乎可能性很小)。

这种方法有什么我遗忘或遗漏的吗?

再次感谢大家,您的反馈意见。我真的很感激。



 类似资料:
  • 使用thoses和JPA属性 Ehcache对于相同的查询不是有效的, 问题与QueryCache类的函数namedParameters.hashCode()有关,它为同一个查询生成不同的HashCode! 这与类有关 它为同一个数组对象[01,1]生成一个不同的(新的)hachCode! 此hashCode方法对于数组应该是递归的

  • 问题内容: 我目前遇到一些问题,以了解为什么在某些情况下Java中的并行化似乎效率低下。在下面的代码中,我构建了4个使用ThreadPool执行的相同任务。 在我的Core i5(2核,4线程)上,如果将工作程序数设置为1,则计算机需要大约5700毫秒,并使用25%的处理器。如果将工作程序数量设置为4,则可以观察到100%的CPU使用率,但是…计算时间是相同的:5700ms,而我希望它可以减少4倍

  • 问题内容: 我正在尝试使用SWIG为python包装一个C ++库。该库通过将 某些类型的回调函数 传递给类方法来频繁使用回调函数。 现在,在包装代码之后,我想从python创建回调逻辑。这可能吗?这是我正在尝试发现的实验..目前不起作用。 头文件和swig文件如下: paska.h: paska.i: 最后,我在python中测试.. 最后一行抛出“ TypeError:方法’handleri_

  • 我正在使用GAE部署我的应用程序,我想把一些环境变量传递给我的GAE实例。例如,每次我使用DB时,分配当前是这样的: 这很好,但问题是它是一个共享代码,每次有人进行本地测试时,它都会更改路径,并将更改推送到存储库。当有人拉动新的更改时,它需要更改以发出db请求,因为每个人都有不同的套接字更改路径。因此,我创建了以下声明: 因此,如果某个人的系统中有一个环境变量,那么它会接受该变量并避免绝对路径。问

  • 假设我们有一个varargs方法,它接受作为输入。将普通字符串[]数组传递给该函数没有问题,但不幸的是,当该方法以其他字符串开头时,它不起作用: 我知道简单地将静态Strings前缀到列表中并传递它是没有问题的,但是在我的特定fc情况下,我的代码的可读性会受到影响,所以如果可能的话,我希望以任何方式避免这种情况。 有可能吗?

  • 问题内容: 我突然在我的java-app(使用NetBeans作为IDE)中创建记录器时,突然看到一条警告:“记录器中字符串连接使用效率不高”。 我的原始代码是 但是NetBeans建议将此代码转换为模板(“模板”在这里意味着什么?),并提供以下代码: 这两种串联方式有什么不同,尽管我从未使用过后者。 干杯。 问题答案: 我会忽略该警告(如果可能,请将其关闭)。串联的效率不是那么低,因为现代编译器