首页 > 解决方案 > 在复杂的不可变对象中初始化集合

问题描述

我有一个复杂的类对象MyClass,我的应用程序将初始化许多(数千个)。应用程序是多线程的,并且这些对象必须可以从多个线程访问。

一些领域的例子是:

final Map<String, Map<RelationSet, Set<String>>> packageRelationSetMap;
final Map<String, Set<String>> compiledUaAccessorySetMap;

为了帮助避免并发问题,我想保证 的实例MyClass是不可变的。

但是,创建每个集合(或集合中的集合中的集合)然后Collections.unmodifiableXXX()每次都将其包装在 a 中是很痛苦的。

我想以集合为例,创建一个内部类MyClass.EventuallyImmutableSet implements Set。基本上它会像这样工作,java.util.Collections.UnmodifiableCollection除了(A)它不会static和(B)而不是自动抛出UnsupportedOperationException类似的方法,它会首先检查(比如)remove()中的布尔变量。MyClassimmutabilityEnabled

我的想法是,然后我可以将MyClass字段修改为

final EventuallyImmutableMap<String, Map<RelationSet, EventuallyImmutableSet<String>>> packageRelationSetMap;
final EventuallyImmutableMap<String, EventuallyImmutableSet<String>> compiledUaAccessorySetMap;

然后我可以像我在构建过程中所做的那样构建集合,并myClassInstance.immutabilityEnabled = true在最后设置以保证不变性(假设这些集合的所有成员本身都是不可变的,并且所有其他对不变性的一般要求......我只是在问在这里收藏)。

这是解决问题的合理有效的方法吗?

更新(回复评论中的问题)

为什么过度嵌套的集合?

例如,

final Map<String, Map<RelationSet, Set<String>>> packageRelationSetMap;

外部映射中的键是一个“包代码”,它与它相关联的是一组附件代码。顺便说一句,我确实有一个Package类可以用来Map代替它的包代码,但这仍然是字段定义:

final Map<Package, Map<RelationSet, Set<String>>> packageRelationSetMap;

...无论如何,稍后,在 jvisualvm 分析显示为性能猪的性能关键和大量使用的代码中,我需要知道,对于每个包,RelationSets它与哪些组件共享通用附件以及设置什么常见的配件是。(我目前每次需要它时都在计算所有这些,而且花费的时间太长)。

我欢迎重构建议作为问题的替代答案。

标签: javaimmutability

解决方案


推荐阅读