Apa arti istilah "bentuk kanonik" atau "representasi kanonik" di Jawa?


90

Saya sering mendengar istilah ini digunakan, tetapi saya tidak pernah benar-benar memahaminya.

Apa artinya, dan adakah yang bisa memberikan beberapa contoh / mengarahkan saya ke beberapa tautan?

EDIT: Terima kasih kepada semua orang atas balasannya. Dapatkah Anda juga memberi tahu saya bagaimana representasi kanonik berguna dalam kinerja equals (), seperti yang dinyatakan di Java Efektif?

Jawaban:


56

Wikipedia menunjuk ke istilah Kanonikalisasi .

Proses untuk mengonversi data yang memiliki lebih dari satu kemungkinan representasi menjadi representasi kanonik "standar". Ini dapat dilakukan untuk membandingkan representasi yang berbeda untuk kesetaraan, untuk menghitung jumlah struktur data yang berbeda, untuk meningkatkan efisiensi berbagai algoritma dengan menghilangkan penghitungan berulang, atau untuk memungkinkan penerapan urutan pengurutan yang bermakna.

Contoh Unicode paling masuk akal bagi saya:

Pengkodean panjang-variabel dalam standar Unicode, khususnya UTF-8, memiliki lebih dari satu kemungkinan pengkodean untuk sebagian besar karakter umum. Ini membuat validasi string lebih rumit, karena setiap kemungkinan pengkodean setiap karakter string harus dipertimbangkan. Implementasi perangkat lunak yang tidak mempertimbangkan semua pengkodean karakter berisiko menerima string yang dianggap tidak valid dalam desain aplikasi, yang dapat menyebabkan bug atau memungkinkan serangan. Solusinya adalah mengizinkan pengkodean tunggal untuk setiap karakter. Kanonikalisasi adalah proses menerjemahkan setiap karakter string ke pengkodean tunggal yang diizinkan. Alternatifnya adalah perangkat lunak untuk menentukan apakah sebuah string dikanonikalisasi, dan kemudian menolaknya jika tidak. Dalam kasus ini, dalam konteks klien / server, kanonikalisasi akan menjadi tanggung jawab klien.

Singkatnya, bentuk representasi standar untuk data. Dari formulir ini Anda kemudian dapat mengubahnya menjadi representasi apa pun yang mungkin Anda perlukan.


64

Saya percaya ada dua penggunaan terkait kanonik: bentuk dan contoh.

Bentuk kanonik berarti bahwa nilai dari jenis sumber daya tertentu dapat dideskripsikan atau direpresentasikan dalam berbagai cara, dan salah satu cara tersebut dipilih sebagai bentuk kanonis yang disukai. (Formulir itu dikanonisasi , seperti buku yang dimasukkan ke dalam Alkitab, dan bentuk lain tidak.) Contoh klasik dari formulir kanonis adalah jalur dalam sistem file hierarki, di mana satu file dapat dirujuk dalam beberapa cara :

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

Definisi klasik dari representasi kanonis file itu akan menjadi jalur terakhir. Dengan jalur lokal atau relatif, Anda tidak dapat mengidentifikasi sumber daya secara global tanpa informasi kontekstual. Dengan jalur absolut, Anda dapat mengidentifikasi sumber daya, tetapi tidak dapat mengetahui apakah dua jalur merujuk ke entitas yang sama. Dengan dua jalur atau lebih yang dikonversi ke bentuk kanonisnya, Anda dapat melakukan semua hal di atas, plus menentukan apakah dua sumber daya sama atau tidak, apakah itu penting untuk aplikasi Anda (selesaikan masalah aliasing ).

Perhatikan bahwa bentuk kanonik dari sumber daya bukanlah kualitas dari bentuk itu sendiri; mungkin ada beberapa kemungkinan bentuk kanonis untuk jenis tertentu seperti jalur file (misalnya, secara leksikografis pertama-tama kemungkinan jalur absolut). Satu formulir hanya dipilih sebagai bentuk kanonik karena alasan aplikasi tertentu, atau mungkin sewenang-wenang sehingga semua orang berbicara dalam bahasa yang sama.

Memaksakan objek ke dalam instance kanonisnya adalah ide dasar yang sama, tetapi alih-alih menentukan satu representasi "terbaik" dari sebuah sumber daya, itu sewenang-wenang memilih satu instance dari kelas instance dengan "konten" yang sama sebagai referensi kanonis, lalu mengonversi semua referensi ke objek yang setara untuk menggunakan satu instance kanonik.

Ini dapat digunakan sebagai teknik untuk mengoptimalkan waktu dan ruang. Jika ada beberapa contoh objek yang setara dalam sebuah aplikasi, maka dengan memaksa semuanya untuk diselesaikan sebagai satu contoh kanonik dari nilai tertentu, Anda dapat menghilangkan semua kecuali satu dari setiap nilai, menghemat ruang dan mungkin waktu karena Anda sekarang dapat membandingkan nilai-nilai tersebut dengan identitas referensi (==) sebagai lawan dari kesetaraan objek ( equals()metode).

Contoh klasik dalam mengoptimalkan performa dengan instance kanonis adalah menciutkan string dengan konten yang sama. Memanggil String.intern()dua string dengan urutan karakter yang sama dijamin akan mengembalikan objek String kanonis yang sama untuk teks tersebut. Jika Anda meneruskan semua string Anda melalui canonicalizer itu, Anda tahu bahwa string yang setara sebenarnya adalah referensi objek yang identik, yaitu alias

Jenis enum di Java 5.0+ memaksa semua instance dari nilai enum tertentu untuk menggunakan instance kanonik yang sama dalam VM, meskipun nilainya diserialkan dan dideserialisasi. Itulah mengapa Anda dapat menggunakan if (day == Days.SUNDAY)dengan impunitas di java jika Daysmerupakan tipe enum. Melakukan ini untuk kelas Anda sendiri tentu saja mungkin, tetapi hati-hati. Bacalah Effective Java oleh Josh Bloch untuk detail dan nasihatnya.


31

Contoh yang baik untuk memahami "bentuk / representasi kanonik" adalah dengan melihat definisi tipe data skema XML dari "boolean":

  • "representasi leksikal" dari boolean dapat berupa salah satu dari: {true, false, 1, 0}sedangkan
  • "representasi kanonik" hanya dapat menjadi salah satu dari {true, false}

Ini, pada dasarnya, berarti itu

  • "true"dan "1"dipetakan ke repr kanonik. "true"dan
  • "false"dan "0"dipetakan ke perwakilan kanonik."false"

lihat definisi tipe data skema XML w3 untuk boolean


28

Kata "canonical" hanyalah sinonim dari "standar" atau "biasa". Itu tidak memiliki arti khusus Java.


3
canonical memiliki arti yang lebih kaya dari IMO standar atau biasa.
cumi

20

direduksi menjadi bentuk yang paling sederhana dan paling signifikan tanpa kehilangan keumuman


5

Cara mudah untuk mengingatnya adalah cara "kanonik" digunakan di kalangan teologis, kebenaran kanonik adalah kebenaran yang sebenarnya jadi jika dua orang menemukannya, mereka telah menemukan kebenaran yang sama. Sama dengan instance kanonik. Jika Anda pikir Anda telah menemukan dua dari mereka (yaitu a.equals(b)) Anda benar-benar hanya memiliki satu (yaitu a == b). Jadi persamaan menyiratkan identitas dalam kasus objek kanonik.

Sekarang untuk perbandingan. Anda sekarang memiliki pilihan untuk menggunakan a==b atau a.equals(b) , karena mereka akan menghasilkan jawaban yang sama dalam kasus contoh kanonik tetapi a == b adalah perbandingan referensi (JVM dapat membandingkan dua angka dengan sangat cepat karena mereka hanya dua pola 32 bit yang dibandingkan untuk a.equals(b)yang adalah panggilan metode dan melibatkan lebih banyak overhead.


2

Contoh bagus lainnya mungkin: Anda memiliki kelas yang mendukung penggunaan koordinat kartesius (x, y, z), bola (r, theta, phi) dan silinder (r, phi, z). Untuk tujuan menetapkan persamaan (metode sama), Anda mungkin ingin mengubah semua representasi menjadi satu representasi "kanonik" yang Anda pilih, misalnya koordinat bola. (Atau mungkin Anda ingin melakukan ini secara umum - yaitu menggunakan satu representasi internal.) Saya bukan seorang ahli, tetapi hal ini terjadi pada saya sebagai contoh konkret yang baik.


0

representasi canonical artinya melihat karakter dengan gaya berbeda misalnya jika saya menulis huruf A berarti orang lain dapat menulis huruf A dengan gaya berbeda :)

Ini sesuai dengan KOLOM PENGENALAN KARAKTER OPTIK



0

Pertanyaan OP tentang bentuk kanonik dan bagaimana itu dapat meningkatkan kinerja equalsmetode keduanya dapat dijawab dengan memperluas contoh yang disediakan di Java yang Efektif.

Pertimbangkan kelas berikut:

public final class CaseInsensitiveString {

  private final String s;

  public CaseInsensitiveString(String s) {
    this.s = Objects.requireNonNull(s);
  }

  @Override 
  public boolean equals(Object o) {
    return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
  }
}

The equalsmetode dalam contoh ini telah menambahkan biaya dengan menggunakan String's equalsIgnoreCasemetode. Seperti yang disebutkan dalam teks

Anda mungkin ingin menyimpan formulir kanonis dari bidang tersebut sehingga metode yang sama dapat melakukan perbandingan tepat yang murah pada formulir kanonis daripada perbandingan tidak standar yang lebih mahal.

Apa yang dimaksud Joshua Bloch ketika dia mengatakan bentuk kanonik ? Saya rasa jawaban singkat Dónal sangat tepat. Kita dapat menyimpan Stringbidang yang mendasari dalam CaseInsensitiveStringcontoh dengan cara standar , mungkin dalam bentuk huruf besar String. Sekarang, Anda dapat mereferensikan bentuk kanonik dari CaseInsensitiveString, varian huruf besar, dan melakukan evaluasi murah dalam metode equalsdan Anda hashcode.


0

Data Kanonis dalam RDBMS, Data Grafik;
Pikirkan sebagai "Normalisasi" atau "Bentuk normal" dari suatu data dalam RDBMS. Data yang sama ada di tabel berbeda, diwakili dengan pengenal unik dan dipetakan dalam tabel berbeda.
atau
Pikirkan satu bentuk data dalam Database Grafik yang direpresentasikan dalam banyak tiga kali lipat.

Manfaat utamanya adalah membuat Dml (Manipulasi data) lebih efisien karena Anda hanya dapat menaikkan (menyisipkan / memperbarui) satu nilai, bukan banyak.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.