Javaの「正規形」または「正規表現」という用語はどういう意味ですか?


90

私はこの用語が使用されていることをよく耳にしますが、それを本当に理解したことはありません。

それはどういう意味ですか、そして誰かがいくつかの例を挙げたり、私にいくつかのリンクを示したりできますか?

編集:返信いただきありがとうございます。効果的なJavaで述べられているように、正規表現がequals()パフォーマンスでどのように役立つかについても教えてください。

回答:


56

ウィキペディアは正規化という用語を指します。

複数の可能な表現を持つデータを「標準」の正規表現に変換するプロセス。これにより、等価性の異なる表現を比較したり、個別のデータ構造の数をカウントしたり、繰り返し計算を排除してさまざまなアルゴリズムの効率を向上させたり、意味のある並べ替え順序を課したりすることができます。

Unicodeの例では、私にはほとんど意味を成していました。

Unicode標準の可変長エンコーディング、特にUTF-8では、ほとんどの一般的な文字に対して複数のエンコーディングが可能です。これにより、各文字列文字のすべての可能なエンコーディングを考慮する必要があるため、文字列の検証がより複雑になります。すべての文字エンコーディングを考慮しないソフトウェア実装では、アプリケーション設計で無効と見なされる文字列を受け入れるリスクがあり、バグの発生や攻撃の可能性があります。解決策は、文字ごとに単一のエンコーディングを許可することです。正規化は、すべての文字列文字を単一の許可されたエンコーディングに変換するプロセスです。別の方法として、ソフトウェアが文字列が正規化されているかどうかを判断し、正規化されていない場合は拒否します。この場合、クライアント/サーバーのコンテキストでは、正規化はクライアントの責任になります。

要約すると、データの標準的な表現形式です。このフォームから、必要に応じて任意の表現に変換できます。


64

正規形には、フォームとインスタンスの2つの関連する使用法があると思います。

標準形式のリソースの特定のタイプの値が記述または複数の方法で表され、それらのいずれかの方法が好まれる標準形式として選択されることができることを意味します。(すなわちフォームがさ列聖聖書にそれを作った書籍のような、および他の形態ではない。)標準形式の典型的な例は、単一のファイルがいくつかの方法で参照することができる階層型ファイルシステムのパスであります:

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

そのファイルの標準的な表現の古典的な定義が最後のパスになります。ローカルパスまたは相対パスでは、コンテキスト情報がないとリソースをグローバルに識別できません。絶対パスを使用すると、リソースを識別できますが、2つのパスが同じエンティティを参照しているかどうかはわかりません。正規の形式に変換された2つ以上のパスを使用すると、上記のすべてを実行でき、さらに2つのリソースが同じかどうかを判断できます(アプリケーションで重要な場合)(エイリアスの問題を解決します)。

リソースの標準形式は、その特定の形式自体の品質ではないことに注意してください。ファイルパスのような特定のタイプには、複数の正規形が存在する可能性があります(たとえば、辞書順で最初にすべての可能な絶対パス)。特定のアプリケーション上の理由から、1つのフォームが正規フォームとして選択されているか、任意に選択されているため、全員が同じ言語を使用できます。

オブジェクトを正規のインスタンスに強制することは同じ基本的な考え方ですが、リソースの「最良の」表現を1つ決定する代わりに、正規の参照と同じ「コンテンツ」を持つインスタンスのクラスのインスタンスを任意に選択し、すべての参照を変換します。 1つの正規インスタンスを使用するために同等のオブジェクトに。

これは、時間と空間の両方を最適化する手法として使用できます。アプリケーション内に同等のオブジェクトのインスタンスが複数ある場合、それらをすべて特定の値の単一の正規インスタンスとして解決するように強制することにより、各値の1つを除くすべてを排除でき、比較できるようになり、スペースと時間を節約できます。オブジェクトの同等性(equals()メソッド)とは対照的に、参照ID(==)を持つ値。

正規インスタンスでパフォーマンスを最適化する典型的な例は、同じ内容の文字列を折りたたむことです。String.intern()同じ文字シーケンスで2つの文字列を呼び出すと、そのテキストに対して同じ正規のStringオブジェクトが返されることが保証されます。すべての文字列をその正規化子に通すと、同等の文字列が実際には同一のオブジェクト参照、つまりエイリアスであることがわかります

Java 5.0以降の列挙型では、特定の列挙値のすべてのインスタンスが、値がシリアル化および逆シリアル化されている場合でも、VM内の同じ正規インスタンスを使用するように強制します。これが、列挙型のif (day == Days.SUNDAY)場合、Javaでそのまま使用できる理由ですDays。独自のクラスでこれを行うことは確かに可能ですが、注意してください。詳細とアドバイスについては、Josh BlochによるEffective Javaをお読みください。


31

「正規の形式/表現」を理解するための良い例は、「boolean」のXMLスキーマデータ型定義を見ることです。

  • ブールの「字句表現は、」のいずれかになります。{true, false, 1, 0}一方、
  • 「正規表現」は、 {true, false}

これは、本質的に、

  • "true"そして"1"標準的なのreprにマッピングされます。"true"そして
  • "false"そして"0"canoncialのreprにマッピングされます。"false"

ブール値のw3 XMLスキーマデータ型定義を参照してください


28

「正規」という言葉は、「標準」または「通常」の同義語です。Java固有の意味はありません。


3
canonicalは、標準または通常のIMOよりも意味が豊富です。
イカ、

20

一般性を失うことなく、最も単純で最も重要な形式に削減


5

それを覚える簡単な方法は、「正準」が神学界で使用されている方法です。正準は真実なので、2人が同じ真実を見つけた場合、正規インスタンスと同じです。それらの2つ(つまりa.equals(b))を見つけたと思う場合は、実際には1つ(つまりa == b)しかありません。したがって、平等は正準オブジェクトの場合には同一性を意味します。

比較のために。これで、使用しての選択肢を持っているa==b か、 a.equals(b)彼らは正規のインスタンスの場合に同じ答えを生成しますが、== bが、彼らは比較ちょうど2つの32ビットパターンがそうであるように、非常に急速に(JVMは、2つの数値を比較することができ、参照の比較であることから、a.equals(b)どのメソッド呼び出しで、より多くのオーバーヘッドを必要とします。


2

もう1つの良い例は、デカルト座標(x、y、z)、球面座標(r、theta、phi)、および円柱座標(r、phi、z)の使用をサポートするクラスがある場合です。等式を確立するために(equalsメソッド)、おそらくすべての表現を、選択した1つの「標準的な」表現(球座標など)に変換する必要があります。(または、一般的にこれを実行する必要がある場合があります。つまり、1つの内部表現を使用します。)私は専門家ではありませんが、これはおそらく良い具体例として私に起こりました。


0

正規表現とは、文字を別のスタイルで表示することを意味します。たとえば、文字Aを書いた場合、別の人が別のスタイルで文字Aを書いてもよいことを意味します。

これは、光学特性認識フィールドによると



0

正規形式に関するOPの質問と、それがequalsメソッドのパフォーマンスをどのように向上させることができるかは、Effective Javaで提供されている例を拡張することで解決できます。

次のクラスについて考えてみます。

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);
  }
}

equalsこの例の方法では、StringequalsIgnoreCase方法を使用することでコストが追加されています。本文で述べたように

equalsメソッドは、コストのかかる非標準の比較ではなく、正規形式で安価な正確な比較を行うことができるように、フィールドの正規形式を格納することができます。

Joshua Blochが正規形と言ったときの意味は?まあ、ドナルの簡潔な答えは非常に適切だと思います。例の基礎となるStringフィールドは、標準的な方法で、おそらく大文字の形式で格納できます。これで、この大文字のバリアントの正規形を参照し、およびメソッドで安価な評価を実行できます。CaseInsensitiveStringStringCaseInsensitiveStringequalshashcode


0

RDBMSの正規データ、グラフデータ。
RDBMS内のデータの「正規化」または「正規形」と考えてください。同じデータが異なるテーブルに存在し、一意の識別子で表され、それを異なるテーブルにマッピングしました。
または
多くのトリプルで表されるグラフデータベースのデータの単一のフォームを考えます。

多くの代わりに1つの値のみをアップサート(挿入/更新)できるため、Dml(データ操作)をより効率的にすることの主な利点です。

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