Apa pro dan kontra dari memiliki jenis CaseInsensitiveString di Jawa? [Tutup]


8

Saya tergoda untuk membuat final class CaseInsensitiveString implements CharSequence.

Ini akan memungkinkan kita untuk mendefinisikan variabel dan bidang jenis ini, daripada menggunakan biasa String. Kita juga dapat memiliki misalnya a Map<CaseInsensitiveString, ?>, a Set<CaseInsensitiveString>, dll.

Apa saja pro dan kontra dari pendekatan ini?


Kekhawatiran potensial: ruang, kebutuhan untuk magang, kinerja, pengumpulan sampah, dll.
polygenelubricants

Jawaban:


26

Ketidak sensitifan huruf adalah properti dari perbandingan, bukan dari objek (*). Anda ingin membandingkan string yang sama secara independen dari kasing atau tidak tergantung pada konteksnya.

(Dan Anda memiliki semua jenis cacing karena perbandingan kasusnya tidak sensitif tergantung pada bahasanya - saya menggunakan huruf besar sebagai İ dalam bahasa Turki - dan bahkan konteksnya - tergantung pada kata dan dialeknya ß dapat dituliskan sebagai SS atau SZ dalam bahasa Jerman.)

(*) Ini bisa menjadi properti dari objek yang berisi string, tetapi itu agak berbeda dari menjadi properti dari string itu sendiri. Dan Anda dapat memiliki kelas yang tidak memiliki keadaan kecuali string, dan membandingkan dua contoh dari kelas itu akan menggunakan perbandingan case tidak sensitif dari string. Tetapi kelas itu tidak akan menjadi string tujuan umum karena tidak akan memberikan metode yang diharapkan untuk string tujuan umum dan akan memberikan metode yang tidak. Kelas ini tidak akan disebut CaseInsensitiveString tetapi PascalIdentifier atau apa pun yang berkaitan untuk menggambarkannya. Dan BTW, algoritma perbandingan kasus independen kemungkinan besar akan disediakan oleh tujuannya dan bersifat lokal independen.


1
Jadi, akankah Anda merekomendasikan TreeSet<String>penggunaan String.CASE_INSENSITIVE_ORDERlebih dari satu HashSet<CaseInsensitiveString>? Perhatikan bahwa menggunakan TreeSetsarana O(log n)untuk contains. Selain itu, komparator ini tidak konsisten dengan equals, yang berarti bahwa dihasilkan tersebut TreeSettidak mematuhi umum Setkontrak (yaitu hal itu mungkin contains(x), meskipun ia tidak memiliki unsur yang equalske x).
polygenelubricants

Sejak pertengahan 90, tabel hash generik yang saya rancang mengambil fungsi hash dan fungsi kesetaraan sebagai parameter generik dengan standar yang disimpulkan dari tipe kunci. (Jika bukan itu yang disediakan oleh perpustakaan Java, saya akan mengambil risiko penjelasan bahwa mereka dirancang oleh seseorang yang lebih akrab dengan pemrograman OO daripada pemrograman generik, mengetik kuat jenis dengan operasi itu adalah sesuatu yang perlu Anda lakukan di OOP tetapi bau kode di GP).
Pemrogram

@AProgrammer Koleksi Java menggunakan equals()implementasi pada setiap objek. Ada implementasi default, yang bisa ditimpa oleh objek apa pun. Saya tidak berpikir Anda dapat mendefinisikan hash, tapi kemudian saya tidak pernah mencoba - tabel selalu bekerja dengan baik tanpa khawatir tentang hal itu (satu alasan saya suka Java lebih dari C ++ :)).
Michael K

1
@AProgrammer - Saya tidak setuju dengan "Ketidakpekaan huruf adalah properti perbandingan, bukan objek", dan dengan ketentuan "mungkin objek tetapi bukan string". Ini mungkin menggambarkan bagaimana keadaannya, tetapi pertanyaannya adalah tentang perubahan yang diusulkan untuk bagaimana keadaannya. Dalam modulo 3 aritmatika, 2 adalah singkatan untuk {..., -4, -1, 2, 5, 8, 11, ...}. Notasi merupakan abstraksi, tetapi tidak sama dengan abstraksi. Mengapa 'H' tidak bisa mewakili abstraksi {'h', 'H'}? Karakter tidak ada dalam memori komputer sama sekali - apakah kode mewakili 'H' atau {'h', 'H'}, itu adalah abstraksi.
Steve314

1
@AProgrammer - pada paragraf kedua, saya mungkin setuju. Paling tidak, itu akan menyiratkan string case-insensitive Bahasa Inggris, string case-insensitive Turki, dll. Kelas dengan subclass atau opsi i18n, TKI. Dan kemudian Anda mendapatkan masalah pengiriman ganda (cara membandingkan dua string case-insensitive dengan opsi bahasa yang berbeda). Saya kira itu kembali ke "properti perbandingan". Sial!
Steve314

7

Tak jauh dari kepala saya:

Pro:

  • Membuat banyak kode untuk mendokumentasikan diri sendiri, misalnya:
    • bool UserIsRegistered(CaseInsensitiveString Username)
  • Semoga merampingkan perbandingan
  • Dapat menghapus potensi bug pembanding

Cons:

  • Mungkin buang-buang waktu saja
    • orang bisa mengonversi string reguler menjadi huruf kecil jika mereka membutuhkan perbandingan case-insensitive
  • Menggunakannya untuk kode front-end akan menyebabkan masalah kapitalisasi
    • Misalnya, jika Anda menggunakan CaseInsensitiveStringuntuk menyimpan nama pengguna, meskipun masuk akal untuk memiliki perbandingan back-end case-insensitive, kode front-end akan menampilkan nama pengguna sebagai "bob smith" atau "BOB SMITH"
  • Jika basis kode Anda sudah menggunakan string biasa, Anda harus kembali dan mengubahnya atau hidup dengan tidak konsisten

4
Bergantung pada implementasinya, poin "Kontra" kedua Anda tidak harus valid - Anda dapat menerapkan CaseInsensitiveString untuk menyimpan case-sensitive dan hanya mengganti operator pembanding.
Pelaku

1
@tdammers: jika CaseInsensitiveString disimpan dengan case dan kemudian dengan operator perbandingan ditimpa, itu memperkuat titik @AProgrammer bahwa operator perbandingan bisa dipisahkan dari objek string apa pun.
rwong

3
@tdammers - beberapa hal sudah bekerja dengan cara yang sama. Sistem file Windows menyimpan case, misalnya, tetapi case-sensitive untuk perbandingan. Ini bukan sistem yang buruk, tetapi dapat menyebabkan kebingungan ketika Anda ingin "mengganti nama" sesuatu untuk mengubah kasus ini. Pada dasarnya, Anda kadang-kadang masih perlu perbandingan case-sensitive untuk menghindari membuat penilaian buruk tentang apakah suatu perubahan nama membuat perubahan asli - dan jika ada satu kasus khusus, mungkin ada yang lain juga.
Steve314

@ rwong: Saya setuju. Hal terbaik adalah perbandingan case-insensitive eksplisit di mana diperlukan. Namun, terkadang Anda ingin string berperilaku seperti string SQL (dengan susunan CI), dan kemudian menjaga case pada penyimpanan tetapi mengabaikan case pada perbandingan akan menjadi pertandingan yang paling dekat.
tdammers

4

CaseInsensitiveString bukan ide yang buruk tergantung pada penggunaan Anda, selama Anda tidak mengharapkannya untuk bekerja sama dengan String.

Anda dapat mengonversi CaseInsensitiveString ke String, atau sebaliknya, dan hanya itu yang harus Anda lakukan.

Masalah akan terjadi jika Anda mencoba melakukan sesuatu seperti

class CaseInsensitiveString {
  private String value;

  public boolean equals(Object o) {
    // .....
    if (o instanceof String) {
      return value.equalsIgnoreCase((String) o);
    }
  }
}

Anda pasti akan gagal jika Anda akan membuat perusahaan CaseInsensitiveString Anda dengan String normal, karena Anda akan melanggar simetris dan transitif-ness untuk equals () (dan kontrak lainnya)

Namun, harap tanyakan pada diri sendiri, dalam hal apa Anda benar-benar membutuhkan CaseInsensitiveString ini yang tidak cocok untuk menggunakan String.CASE_INSENSITIVE_ORDER? Saya yakin tidak banyak kasus. Saya yakin akan ada kasus yang layak memiliki kelas khusus ini, tetapi tanyakan pada diri Anda terlebih dahulu.


2

Membuat jenis secara eksplisit dalam domain / model Anda adalah praktik yang sangat baik. Seperti yang dikatakan Maxpm, ini adalah dokumentasi sendiri. Juga nilai tambah yang besar: orang tidak dapat (secara tidak sengaja) menggunakan input yang salah. Satu-satunya hal negatif yang dimilikinya adalah bahwa ia akan menakut-nakuti programmer junior (dan bahkan beberapa mediator).


1

Kelas CaseInsensitiveString dan pembantunya menambahkan banyak kode dan mereka akan membuat semuanya lebih mudah dibaca daripada metode String.toLoweCase ().

CaseInsensitiveString vaName1 = new CaseInsensitiveString('HeLLo');
//... a lot of lines here
CaseInsensitiveString vaName2 = new CaseInsensitiveString('Hello');
//... a lot of lines here
if (varName1.equals(varName2)) ...

lebih kompleks, kurang mendokumentasikan diri, dan kurang fleksibel daripada

String vaName1 = 'HeLLo';
//... a lot of lines here
String vaName2 = 'Hello';
//... a lot of lines here
if (varName1.toLowerCase().equals(varName2.toLowerCase())) ...

0

Implementasi yang paling sering digunakan di web adalah case-sensitive - XML, JavaScript. Dalam hal kinerja, selalu terbaik untuk menggunakan fungsi / properti / objek yang paling tepat untuk setiap kasus.

Jika Anda berurusan dengan struktur - XML ​​atau JS atau yang serupa, sensitivitas huruf adalah penting. Jauh lebih cepat menggunakan pustaka sistem.

Jika Anda berurusan dengan data dalam basis data, seperti yang disebutkan di atas, pengindeksan basis data harus digunakan untuk string case / sensitive case.

Jika Anda menangani data dengan cepat, penting untuk membuat perhitungan biaya konversi yang diperlukan untuk setiap string. Mungkin string harus dibandingkan atau diurutkan entah bagaimana.

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.