У меня есть сложный объект класса MyClass
, который мое приложение будет инициализировать многие (тысячи). Приложение является многопоточным, и эти объекты должны быть доступны из нескольких потоков.
Примеры некоторых полей:
final Map<String, Map<RelationSet, Set<String>>> packageRelationSetMap;
final Map<String, Set<String>> compiledUaAccessorySetMap;
Чтобы избежать проблем параллелизма, я хочу гарантировать, что экземпляры MyClass
являются неизменяемыми.
Но создание каждой коллекции (или коллекции в коллекции внутри коллекции) - это боль, а затем каждый раз оборачивать ее в Collections.unmodifiableXXX()
.
У меня была мысль сделать, используя наборы в качестве примера, внутренний класс MyClass.EventuallyImmutableSet implements Set
. В основном это будет работать так же, как java.util.Collections.UnmodifiableCollection
, за исключением того, что (A) это не будет static
и (B) вместо автоматического броска UnsupportedOperationException
в таких методах, как remove()
, сначала будет проверена логическая переменная в MyClass
(скажем immutabilityEnabled
).
Я думаю, что тогда я мог бы изменить поля 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
, с которым он разделяет общие аксессуары и каков этот набор общих аксессуаров является. (В настоящее время я вычисляю все это каждый раз, когда мне это нужно, и это занимает слишком много времени.)
Я приветствую предложения по рефакторингу в качестве альтернативного ответа на вопрос.