Minha pergunta é bastante uma questão de design. No meu programa, cheguei a uma estrutura de dados que se parece com isso:
private ConcurrentHashMap<A, ConcurrentHashMap<B, ConcurrentHashMap<Integer, C>>> services = new ConcurrentHashMap<A, ConcurrentHashMap<B, ConcurrentHashMap<Integer, C>>>();
Existe uma maneira de lidar com essa estrutura de dados de maneira mais elegante? Obrigado!
editar : A, B e C são classes de negócios. Uma instância A "pode ter" (como associação) muitos Bs e um B "pode ter" muitos mapeamentos Integer-C.
java
design
data-structures
ovdsrn
fonte
fonte
A
,B
eC
? Seria mais fácil responder se eu pudesse entender o significado do aninhamento em três níveis dos seus mapas lá.ConcurrentHashMap
s em todos os níveis de aninhamento?Respostas:
Crie uma classe
Triple
com campos paraA
,B
,Integer
, overridehashCode()
eequals()
e usoMap<Triple,C>
, em vez deMap<A,Map<B,Map<Integer,C>>>
Nesta abordagem - você coloca todos os elementos em um mapa, com um maior número possível de chaves.
fonte
(A,B,Integer)
->C
e, portanto, oMap
uso aninhado . A edição também suporta minha precepção.equals
, isso só funcionará se as chaves formarem uma relação de equivalência. Recentemente, encontrei uma situação como essa em que não: o terceiro componente da chave poderia ser um valor padrão que aceitaria qualquer instância ou algum valor concreto, com todos os valores concretos sendo diferentes um do outro. Assim, qualquer valor concreto teria que ser considerado igual ao padrão e, por transitividade, todos teriam que ser iguais um ao outro, o que não eram.[Eu venho de background em C #, mas a resposta deve ser aplicada]
[Não importa muito, mas presumo que o último item seja ConcurrentHashMap <C, Inteiro> ]
Você tem uma função f do tipo A -> (B -> (C -> int)). Se é realmente o que você precisa, não tenho uma resposta pronta. Mas talvez, ter uma função f do tipo (A x B x C) -> int seja suficiente para seus propósitos.
A diferença entre dois casos é que o primeiro é mais preguiçoso, mais funcional, sem dúvida mais elegante e é possível ter uma função "parcialmente aplicada". Por exemplo, você tem uma um (do tipo A) elemento, você aplicar um para f e têm uma função g do tipo (B -> (C -> int)) para passar ao redor, enviar para métodos, seja qual for. No entanto, é um pouco complicado e um pouco mais de código para inicializar corretamente a função.
O segundo é mais ávido e menos elegante, mas pode ser mais fácil codificar e entender. Tudo que você precisa fazer é ter uma classe genérica Triple <A, B, C> , substituir Equals () e GetHashCode () para que ela tenha semântica de valor (duas instâncias serão consideradas iguais se tiverem elementos iguais) e declare que o ConcurrentHashMap é de Triplo para Inteiro . O custo mais óbvio a pagar é que você precisa ter os elementos A , B , C prontos de uma só vez para criar uma instância do Triple e executar a pesquisa.
Edit: Se o último item for realmente ConcurrentHashMap <C, Inteiro> , sua classe genérica terá campos A , B e Inteiro , e o mapeamento será de Triplo <A, B, Inteiro> para C
fonte
Triple
vez deMyClass
esclarecer; também existem implementações de n-tupla na web, se você é realmente preguiçoso.