2011-07-10 15 views
4

文字列の一意の数値表現を取得したい。私はこれを行う方法がたくさんあることを知っています、私の質問はあなたが最高だと思いますか?私は負の数を持つことは望まないので、Javaのhashcode()関数はそれほど優れていませんが、私はそれを上書きすることができます...しかし、私は自信がなく、誤って何かを壊す。双方向文字列ハッシュ関数

私の文字列はすべてsemantic-web URISです。数値表現の理由は、ページのURIのデータを表示するときに、クエリ文字列に渡すか、またはJavaScriptのさまざまなフィールドに入力する必要があるためです。 URI自体が扱いにくく、URIの値としてURIを持つと悪いように見えます。

基本的に私はあなたが提案場合は、これを行うだろう機能することができ、この

Resource{ 
    int id; 
    String uri; 
    String value; // this is the label or human readable name 

    // .... other code/getters/setters here 

    public int getId(){ 
    return id = stringToIntFunction(); 
    } 

    private int stringToIntFunction(String uri){ 
    // do magic here 
    } 
} 

のようになります。Resourceというクラスがしたい:、それは双方向でなければならなかった

  1. をことを数値から元の文字列を復元することもできますか?
  2. これは双方向である必要はありません。

私が検討していない他の重要な問題もありますか?

+0

"双方向ハッシュ関数"は暗号化、はいですか? –

答えて

12

可逆性にしたい場合は、困っています。ハッシュはの一方向に設計されています。

特に、intには32ビットの情報があり、charには16ビットの情報があるため、可逆性を必要とするということは、0文字、1文字または2文字の文字列しか持てないことを意味します。 「\ 0 \ 0」またはそれに類するものとしてエンコードすることができます)。もちろん、ストレージがないと仮定しています。あなたがストレージを使用できる場合は、単に数字を順番に格納し、その後、...のようなもの:ここで

private int stringToIntFunction(String uri) { 
    Integer existingId = storage.get(uri); 
    if (existingId != null) { 
     return existingId.intValue(); 
    } 
    return storage.put(uri); 
} 

storage.put()は、内部カウンタを増加させるカウンタ値に関連するものとしてURIを格納し、それを返します。私の推測は、それはあなたが何をしているかではないということです。

基本的に、可逆暗号化を実行するために、私は(例えば、UTF-8を使用して)最初のバイナリ形式に文字列を変換した標準の暗号化ライブラリを使用したいです。結果はbyte[]であると私は期待しています。

それはは可逆である必要はありません場合は、私はその絶対値がintとして表すことができないとしてだけで、通常のhashCode()結果の絶対値をとる(ただし、特定の何かにInteger.MIN_VALUEをマッピング検討したいです)。

+0

ありがとうジョン、私はあなたの2番目の提案と一緒に行かなければならないかもしれません。しかし、私はあなたが何を意味するのかはわかりません '特定のものにInteger.MIN_VALUEをマッピングします。その絶対値はintとして表現できません。' – Ankur

+0

一方的な状況では材料が豊富ですそこに(そしてSOに) – Ankur

+1

@Ankur:Integer.MIN_VALUEの絶対値は2,147,483,648です。しかし、整数が表すことができる最大の正の数は2,147,483,647です。だから、Integer.MIN_VALUEでMath.absを呼び出さずに、別の方法でそれを処理する必要があります。 –

7

ハッシュは一方向のみです(入力サイズに関係なく固定長になっている理由の一部です)。双方向が必要な場合は、Base64エンコーディングのようなものを探しています。

なぜあなたは負の数を持つことができませんか? URIはどこから来たのですか?彼らはデータベースに入っていますか?なぜデータベースキーIDを使用しないのですか?それらがデータベースにない場合は、変数/パラメータのセットを与えられたユーザーに対してそれらを生成できますか?(クエリ文字列にはfoo = 1 & bar = 2のようなものしか含まれず、サーバー側またはJavaScript側でURLを生成します)

+0

非常に長い説明を(非常に小さなボックスに)保存するために、私はdbキーIDを使用していると言いたいが、これは私のアプリケーションの別のセクションでパフォーマンスを殺す。 – Ankur

+0

@Ankurこれをキャッシュで解決する可能性はありますか?本質的にJonが提案する、グローバルなHashtable。 –

+0

ありがとうございます。私が考えているのは、1)ハッシュ値を計算する、2)数値順にストアする、3)このテーブルを定期的に見て、A、B、Cなどをハッシュの2番目、3番目、 。私はそれが厳密にintである必要はありません(いいかもしれませんが)ことを述べている必要があります。コンパクトなもの。 – Ankur

2

"ユニークな表現"は、Java提供のstring.hashcodeが役に立たないことを意味します。同じハッシュコードを共有していた2つのURIをすぐに見つけることができます。

任意の2ウェイ方式は扱いにくい文字列をもたらすために起こっている - あなたは、データベース内のURIを格納し、あなたの一意の識別子としてのレコードIDを使用しない限り。

片方向に行く限り、MD5ハッシュは単純なハッシュコードよりもはるかにユニークではありますが、ユニークではありませんが、あなたの定義に応じて「扱いにくい」と考えるかもしれません!上記の行われたすべてのremars考える

3

(ハッシュ関数は一つの方法です)、私は2つの可能な解決策のために行くだろう:

  • あなたのURLを表す長い文字列を取得するには、いくつかの暗号化機能を使用してください(あなたが何かを得るでしょう - > param = 456ab894ce897b98fのように(これはURLによって長くても短くてもかまいません)DES暗号化(例:base64url
  • URLをデータベースに保存しておくこともできますSQLiteなど)を使用すると、効果的にuintを得ることができます< => URLの同等性
+0

ありがとうございました。 – Ankur

0

Q1:あなたは数から文字列を回復したいなら、あなたは使用することができます:

1A:文字列の暗号化、同じ大きさ、または長くなるだろう、あなたは文字列を圧縮しない限り、最初。これは、ランダムに見えるバイトの配列を返します。これは、Base-64として表示されます。

1B:データベース、またはマップ、および数は、地図/データベース内の文字列のインデックスです。

Q2:文字列を復元する必要はありません。

ここではさまざまなアイデアが可能です。ハッシュを16進数で表示するか、Base-64で表示して、マイナス記号を避けることができます。 Base-64の英数字以外の文字は、 '+'、 '/'、 '='のみです。ほとんどユニークなハッシュのためには、暗号サイズ、MD5(128ビット)、SHA-1(160ビット)またはSHA-2(256または512ビット)が必要です。

アンMD5ハッシュは進で「d131dd02c5e6eec4693d9a0698aff95c」のように見えます。ハッシュ値が大きければ大きいほど、衝突は少なくなります。

rossum

+0

-1質問には答えません! –