Acredito que haja dois usos relacionados de canônico: formas e instâncias.
Uma forma canônica significa que os valores de um tipo específico de recurso podem ser descritos ou representados de várias maneiras, e uma delas é escolhida como a forma canônica preferida. (Essa forma é canonizada , como os livros que entraram na Bíblia, e as outras formas não.) Um exemplo clássico de uma forma canônica são caminhos em um sistema de arquivos hierárquico, onde um único arquivo pode ser referenciado de várias maneiras :
myFile.txt # in current working dir
../conf/myFile.txt # relative to the CWD
/apps/tomcat/conf/myFile.txt # absolute path using symbolic links
/u1/local/apps/tomcat-5.5.1/conf/myFile.txt # absolute path with no symlinks
A definição clássica da representação canônica desse arquivo seria o último caminho. Com caminhos locais ou relativos, você não pode identificar globalmente o recurso sem informações contextuais. Com caminhos absolutos, você pode identificar o recurso, mas não pode dizer se dois caminhos se referem à mesma entidade. Com dois ou mais caminhos convertidos em suas formas canônicas, você pode fazer tudo acima, além de determinar se dois recursos são iguais ou não, se isso é importante para o seu aplicativo (resolva o problema de aliasing ).
Observe que a forma canônica de um recurso não é uma qualidade dessa forma particular; pode haver várias formas canônicas possíveis para um determinado tipo, como caminhos de arquivo (digamos, lexicograficamente antes de todos os caminhos absolutos possíveis). Um formulário é apenas selecionado como o formulário canônico para um motivo de aplicação específico, ou talvez arbitrariamente para que todos falem a mesma língua.
Forçar objetos em suas instâncias canônicas é a mesma ideia básica, mas em vez de determinar uma "melhor" representação de um recurso, ele escolhe arbitrariamente uma instância de uma classe de instâncias com o mesmo "conteúdo" da referência canônica e, em seguida, converte todas as referências a objetos equivalentes para usar a única instância canônica.
Isso pode ser usado como uma técnica para otimizar o tempo e o espaço. Se houver várias instâncias de objetos equivalentes em um aplicativo, ao forçar todos eles a serem resolvidos como a única instância canônica de um valor específico, você pode eliminar todos, exceto um de cada valor, economizando espaço e possivelmente tempo, pois agora você pode comparar aqueles valores com identidade de referência (==) em oposição à equivalência de objeto ( equals()
método).
Um exemplo clássico de otimização de desempenho com instâncias canônicas é o recolhimento de strings com o mesmo conteúdo. Chamar String.intern()
duas strings com a mesma sequência de caracteres certamente retornará o mesmo objeto String canônico para aquele texto. Se você passar todas as suas strings através desse canonicalizador, você saberá que strings equivalentes são, na verdade, referências a objetos idênticos, ou seja, aliases
Os tipos de enum em Java 5.0+ forçam todas as instâncias de um determinado valor de enum a usar a mesma instância canônica em uma VM, mesmo se o valor for serializado e desserializado. É por isso que você pode usar if (day == Days.SUNDAY)
impunemente em java se Days
for um tipo enum. Certamente é possível fazer isso em suas próprias aulas, mas tome cuidado. Leia Effective Java de Josh Bloch para obter detalhes e conselhos.
reduzido à forma mais simples e significativa sem perder a generalidade
fonte
Uma maneira fácil de lembrar é a maneira como "canônico" é usado nos círculos teológicos, a verdade canônica é a verdade real, então se duas pessoas a encontrarem, terão encontrado a mesma verdade. Mesmo com a instância canônica. Se você acha que encontrou dois deles (ou seja,
a.equals(b)
) você realmente só tem um (ou sejaa == b
). Portanto, igualdade implica identidade no caso de objeto canônico.Agora, para a comparação. Você agora tem a opção de usar
a==b
oua.equals(b)
, pois eles produzirão a mesma resposta no caso de instância canônica, mas a == b é a comparação da referência (a JVM pode comparar dois números extremamente rapidamente, pois eles são apenas dois padrões de 32 bits comparados para oa.equals(b)
qual é uma chamada de método e envolve mais sobrecarga.fonte
Outro bom exemplo pode ser: você tem uma classe que suporta o uso de coordenadas cartesianas (x, y, z), esféricas (r, teta, phi) e cilíndricas (r, phi, z). Para fins de estabelecer igualdade (método de igualdade), você provavelmente desejaria converter todas as representações em uma representação "canônica" de sua escolha, por exemplo, coordenadas esféricas. (Ou talvez você queira fazer isso em geral - ou seja, usar uma representação interna.) Não sou um especialista, mas isso me ocorreu como um bom exemplo concreto.
fonte
representação canônica significa visualizar o personagem em um estilo diferente, por exemplo, se eu escrever uma letra A, significa que outra pessoa pode escrever a letra A em um estilo diferente :)
Isso está de acordo com o CAMPO DE RECONHECIMENTO DE CARACTERES ÓPTICAS
fonte
Uma forma canônica significa uma representação naturalmente única do elemento
fonte
As perguntas do OP sobre a forma canônica e como ele pode melhorar o desempenho do
equals
método podem ser respondidas estendendo o exemplo fornecido em Effective Java.Considere a seguinte classe:
O
equals
método neste exemplo adicionou custo usandoString
oequalsIgnoreCase
método de. Conforme mencionado no textoO que Joshua Bloch quer dizer quando fala em forma canônica ? Bem, acho que a resposta concisa de Dónal é muito apropriada. Podemos armazenar o
String
campo subjacente noCaseInsensitiveString
exemplo de uma forma padrão , talvez a forma em maiúsculas doString
. Agora, você pode fazer referência a esta forma canônica deCaseInsensitiveString
, sua variante em maiúsculas e realizar avaliações baratas em seus métodosequals
ehashcode
.fonte
Dados canônicos em RDBMS, dados gráficos;
Pense como "Normalização" ou "Forma normal" de dados em um RDBMS. Os mesmos dados existem em tabelas diferentes, representados com um identificador único e mapeados em tabelas diferentes.
ou
Pense em uma única forma de dados no Graph Database que representou em muitos triplos.
O principal benefício disso é tornar o Dml (manipulação de dados) mais eficiente, pois você pode fazer o upsert (inserir / atualizar) apenas um valor em vez de muitos.
fonte