JavaでCaseInsensitiveString型を持つことの長所と短所は何ですか?[閉まっている]


8

を作成したくなりますfinal class CaseInsensitiveString implements CharSequence

これにより、通常のを使用する代わりに、このタイプの変数とフィールドを定義できますString。たとえば、a Map<CaseInsensitiveString, ?>、a Set<CaseInsensitiveString>なども使用できます。

このアプローチの長所と短所は何ですか?


潜在的な懸念:スペース、インターンの必要性、パフォーマンス、ガーベッジ
コレクティビティ

回答:


26

大文字と小文字を区別しないのは、オブジェクト(*)ではなく、比較のプロパティです。大文字小文字を区別せずに、またはコンテキストに関係なく、同じ文字列を比較する必要があります。

(そして、大文字と小文字を区別しない比較は言語に依存するので、あなたはすべての種類のワームを持っています-私はトルコ語ではasとして大文字です-そして文脈-単語と方言によってはßは大文字として大文字にすることができますSSまたはSZ(ドイツ語)。)

(*)文字列を含むオブジェクトのプロパティにすることもできますが、文字列自体のプロパティとは多少異なります。また、文字列以外の状態がないクラスを作成することもできます。そのクラスの2つのインスタンスを比較すると、大文字と小文字を区別しない文字列の比較が使用されます。しかし、そのクラスは、汎用文字列に期待されるメソッドを提供せず、そうでないメソッドを提供するため、汎用文字列にはなりません。このクラスはCaseInsensitiveStringではなく、PascalIdentifierまたはそれを記述するのに適切なものと呼ばれます。ところで、大文字と小文字を区別しない比較アルゴリズムは、おそらくその目的によって提供され、ロケールに依存しません。


1
のでをTreeSet<String>使用することをお勧めString.CASE_INSENSITIVE_ORDERHashSet<CaseInsensitiveString>ますか?使用していることを注意TreeSetする手段をO(log n)ためcontains。また、このコンパレータは、一貫性のないequals結果として得があることを意味し、TreeSet一般的に従わないSet(すなわち、それは5月の契約をcontains(x)それは何の要素がないにもかかわらず、equalsにをx)。
polygenelubricants

90年代半ば以降、私が設計したジェネリックハッシュテーブルは、ハッシュ関数と等式関数の両方をジェネリックパラメーターとして受け取り、デフォルトではキータイプから推定されます。(Javaライブラリによって提供されたものに当てはまらない場合、それらは一般的なプログラミングよりもOOプログラミングに精通している誰かによって設計されたという説明を危険にさらすでしょう、これらの操作で型を強く入力することはあなたがする必要があるものですOOPではコードですが、GPではコードのにおいがします)。
AProgrammer '06 / 07/11

@AProgrammer Javaコレクションは、equals()各オブジェクトの実装を使用します。デフォルトの実装があり、どのオブジェクトでもオーバーライドできます。私はあなたがハッシュを定義できるとは思いませんが、それから私は試したことはありません-テーブルはそれを心配することなく常にうまくいきました(C ++ではなくJavaが好きな理由の1つです:))。
マイケルK

1
@AProgrammer-「大文字と小文字を区別しないことはオブジェクトではなく比較のプロパティである」、および「オブジェクトではあるが文字列ではない」という条件に同意しません。これは物事がどのように説明されるかもしれませんが、問題は物事の方法に提案された変更についてです。3を法とする算術演算では、2は{...、-4、-1、2、5、8、11、...}の省略形です。表記は抽象化を表していますが、抽象化と同じものではありません。'H'が抽象{{h '、' H '}を表現できないのはなぜですか?文字はコンピューターのメモリにまったく存在しません。コードが「H」または{「h」、「H」}を表すかどうかは、抽象化です。
Steve314、2011

1
@AProgrammer-2番目の段落では、多分同意します。少なくとも、英語の大文字と小文字を区別しない文字列、トルコ語の大文字と小文字を区別しない文字列などを意味します。サブクラスを持つクラスまたはi18nオプションIOW。次に、二重ディスパッチの問題が発生します(2つの大文字小文字を区別しない、異なる言語オプションの文字列を比較する方法)。それは「比較の性質」に戻ると思います。くそー!
Steve314、2011

7

私の頭の真上から:

長所:

  • 多くのコードを自己文書化します。例:
    • bool UserIsRegistered(CaseInsensitiveString Username)
  • 比較を合理化できる
  • 比較バグの可能性を取り除く可能性があります

短所:

  • 時間の無駄かもしれません
    • 大文字と小文字を区別しない比較が必要な場合は、通常の文字列を小文字に変換できます
  • フロントエンドコードに使用すると、大文字の問題が発生します
    • たとえば、を使用CaseInsensitiveStringしてユーザー名を保存する場合、大文字と小文字を区別しないバックエンド比較を行うのは理にかなっていますが、フロントエンドコードはユーザーの名前を「bob smith」または「BOB SMITH」として表示します
  • コードベースがすでに通常の文字列を使用している場合は、戻ってそれらを変更するか、矛盾を抱えて生きる必要があります

4
実装によっては、2番目の「短所」ポイントが有効である必要はありません。CaseInsensitiveStringを実装して、大文字と小文字を区別して格納し、比較演算子をオーバーライドするだけです。
tdammers

1
@tdammers:CaseInsensitiveStringが大文字と小文字で格納され、その後比較演算子がオーバーライドされた場合、@ AProgrammerのポイントが強化され、比較演算子が任意の文字列オブジェクトから分離された可能性があります。
rwong 2011

3
@tdammers-いくつかはすでに同じように機能します。たとえば、Windowsファイルシステムでは大文字と小文字が保持されますが、比較では大文字と小文字は区別されません。これは悪いシステムではありませんが、ケースを変更するために何かを「名前変更」するときに混乱を引き起こす可能性があります。基本的に、名前の変更によって本物の変更が行われたかどうかについて誤った判断をしないように、大文字と小文字を区別した比較が必要になる場合があります。特別なケースが1つある場合は、他のケースもある可能性があります。
Steve314、2011

@rwong:同意します。最善の方法は、必要に応じて、大文字と小文字を区別しない明示的な比較です。ただし、文字列を(CI照合を使用して)SQL文字列のように動作させたい場合、ストレージでは大文字と小文字を保持しますが、比較では大文字と小文字を無視するのが最も一致します。
tdammers

4

CaseInsensitiveStringは、Stringと一緒に機能することを期待していない限り、使用方法に依存する悪い考えではありません。

CaseInsensitiveStringをStringに、またはその逆に変換することができます。

次のようなことをしようとすると問題が発生します

class CaseInsensitiveString {
  private String value;

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

equals()(および他のコントラクト)の対称性と推移性に違反するため、CaseInsensitiveStringを通常の文字列で企業化しようとすると、失敗する運命にあります。

ただし、String.CASE_INSENSITIVE_ORDERを使用するのに適さないこのCaseInsensitiveStringが本当に必要な場合は、自問してください。私は多くのケースを賭けません。私はこの特別なクラスを持つ価値があるケースがあると確信していますが、まずあなた自身に尋ねてください。


2

ドメイン/モデルで型を明示的に作成することは非常に良い習慣です。Maxpmが言ったように、それは自己文書化です。また、大きなプラス:人々は(偶然に)間違った入力を使用することはできません。それが持っている唯一の否定的なことは、それがジュニア(そしていくつかのメディア)のプログラマを怖がらせることです。


1

CaseInsensitiveStringクラスとそのヘルパーは多くのコードを追加し、それらはすべてを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)) ...

よりも複雑で、自己文書化が少なく、柔軟性が低い

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

0

Webで最も頻繁に使用される実装では、大文字と小文字が区別されます-XML、JavaScript。パフォーマンスの観点から、常に各ケースに最も適切な関数/プロパティ/オブジェクトを使用することが最善です。

XMLやJSなどの構造を扱う場合は、大文字と小文字を区別することが重要です。システムライブラリを使用すると、はるかに高速になります。

上記のように、データベース内のデータを処理する場合は、データベースのインデックスを使用して、大文字と小文字を区別する/区別しない文字列を作成します。

オンザフライでデータを処理する場合は、文字列ごとに必要な変換コストを計算することが重要です。どういうわけか、文字列を比較またはソートする必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.