2016-10-17 11 views
1

私はJCRベースのアプリケーションで動作し、不正な文字が含まれているとクエリが壊れます。Java8ラムダシーケンシャルまたはパイプ文字列変換

私は本当に単純なタスクを実行しました。クエリ文字列と "dodgy"文字のリストを含むマップが与えられた場合、これらの不正な文字を順番に置き換えて許可された文字に置き換えます。私はラムダを使いたい、と少し立ち往生悲しいことだ:

public static Map<String, String> DODGY_CHARS = getDodgyCharMapping(); 

static Map<String, String> getDodgyCharMapping(){ 
    Map<String, String> map = new HashMap<>(); 
    map.put("'", "''"); 
    return map; 
} 

private String sanitizeQueryString(String query){ 
    DODGY_CHARS.keySet().forEach(key->{ 
     query = replaceCharacter(query, key, DODGY_CHARS.get(key)); 
    }); 
    return query; 
} 

ラムダ内部クエリ変数は、次のようなエラーが生じ、J8はと幸せではないです:

error: local variables referenced from a lambda expression must be final or effectively final 
+2

エラーメッセージには、あなたのラムダでは、外側のスコープの最終変数しか使用できないと言われています...?なぜ伝統的なfor-eachループを使用しないのですか? –

+0

それを宣言する(または2番目の、最終的な変数を宣言すること)どちらもうまくやっていない、私はラムダが前進する方法だと思ったので、私はそれに行くことにしました... –

+1

なぜ使いたいですか?ラムダ?文字を一度(一回)繰り返し、変換されたバージョンから新しい 'StringBuilder'を作成してください。すべてのタスクがlambdasに役立つわけではなく、これもその1つです。 – biziclop

答えて

5

問題は、ラムダ式の本体のスコープ内でローカル変数queryにアクセスしていることです。したがって、finalまたは実質的にfinalでなければなりません。ただし、queryfinalと指定しても、値を割り当てているため問題は解決しません。

replaceCharacterにはStringBuilderがあり、String変数を読み込んだり再割り当てする代わりに内容を置き換えることをお勧めします。

0

役に立つ返信やコメントをいただきありがとうございます。 はい、私は深く掘り下げ始めました。そしてStringBuilderを使用しようとしましたが、文字列内のすべての通貨を置き換える必要があったため、別のネストループで10行以上のコードにすばやくエスカレートしました。

したがって、複雑さを軽減し、コードの可読性を向上させる代わりに、それは正反対です。

はラムダフリー1と比較:ハァッ、

private String sanitizeQueryString(String query){ 
    for (String key: DODGY_CHARS.keySet()){ 
     query = replaceCharacter(query, key, DODGY_CHARS.get(key)); 
    } 
    return query; 
} 

ニースとシンプルな?

教訓:どのようにラムダとしてすべての靴をこまそうとしないでください これらはおしゃれです!

+1

あなたが本当に "コードをデータとして送る"必要がある状況。メソッドに引数として関数を送る場合は、ラムダ豊富な環境が必要です。 – scottb

+2

あなたの地図はかなり小さいと思いますので、それほど大きな違いはありません。しかし、一般的には、ルックアップを避けるために、キーと値の両方にアクセスする必要がある場合は、マップの 'entrySet()'を反復する必要があります。 –

関連する問題