Инициализация коллекций в сложном неизменном объекте - PullRequest
3 голосов
/ 30 января 2020

У меня есть сложный объект класса 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, с которым он разделяет общие аксессуары и каков этот набор общих аксессуаров является. (В настоящее время я вычисляю все это каждый раз, когда мне это нужно, и это занимает слишком много времени.)

Я приветствую предложения по рефакторингу в качестве альтернативного ответа на вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...