2016-07-06 7 views
1

一致する文字列は出力しませんが、結果はnullです。一致しない文字列を印刷するには

public class Replacement { 
    public static void main(String[] ignored) { 

     String str = "aaa bbb ddd"; 
     Map<String, String> mapping = new HashMap<>(); 
     mapping.put("aaa", "hello"); 
     mapping.put("bbb", "java"); 
     mapping.put("ccc", "world"); 

     Pattern pattern = Pattern.compile("([a-zA-Z_]+)"); // pattern compiling 
     Matcher matcher = pattern.matcher(str); // pattern matching 

     StringBuffer sb = new StringBuffer(); 
     while(matcher.find()) { // while matcher found 
     String replace = mapping.get(matcher.group()); 
     matcher.appendReplacement(sb, replace + " "); 
     } 
     matcher.appendTail(sb); 

     System.out.println(sb); 
    } 
} 

結果:

ハローJavaのnull //私はハローJavaのDDDD」期待

私はwhile(!matcher.find())

+1

マップにキー 'dddd'がないので、** null **を返すのは正しいです。 – developer033

答えて

1

あなたは、あなたが欲しいものを達成するために配置する必要がありますか置換が存在するかどうかを確認する必要があります。置換が存在しない場合は、キー自体を追加する必要があります

 String replace = mapping.get(matcher.group()); 
    if(replace==null) { 
     replace = matcher.group(); 
    } 
    matcher.appendReplacement(sb, replace + " "); 

これが役に立ちます。

1

次のコードはIntelliJ 11でテストされており、正しく動作しているようです。私はあなたの意図がstr入力のそれぞれの文字列にマッチして、それがハッシュマップにマッピングを持っているならば、それを置き換えることを考えていると思います。問題は、マップに一致する単語が表示されているかどうかを実際に確認せずに置換を実行していることです。マッチにマッピングがある場合、条件付きで置換を行うロジックを追加しました。

public class Replacement { 
    public static void main(String[] ignored) { 

     String str = "aaa bbb ddd"; 
     Map<String, String> mapping = new HashMap<String, String>(); 
     mapping.put("aaa", "hello"); 
     mapping.put("bbb", "java"); 
     mapping.put("ccc", "world"); 

     Pattern pattern = Pattern.compile("([a-zA-Z_]+)");compiling 
     Matcher matcher = pattern.matcher(str); 

     StringBuffer sb = new StringBuffer(); 
     while(matcher.find()) { 
      String key = matcher.group();  // matched word is key into the map 
      String value = mapping.get(key); // attempt to get mapped word 
      if (value != null) {    // if mapping exists, 
       str = str.replace(key, value); // then make replacement 
      } 
     } 
     System.out.println(str); 
    } 
} 

更新:

あなたは@ajbが指摘何の線に沿ってエッジケースを心配する必要がある場合は、選択的に各単語を置き換え、ちょうどスペースであなたの元の文字列を分割する方が安全だろう、その後、再び単一の文字列にアップし、それをロールバック:

String[] parts = str.split(" "); 
String output = ""; 

for (int i=0; i < parts.length; ++i) { 
    String value = mapping.get(parts[i]); 
    if (value == null) { 
     value = parts[i]; 
    } 

    if (i > 0) { 
     output += " "; 
    } 
    output += value; 
} 
+0

あなたの新しいバージョンは、OPの意図と同じことをするとは思わない。入力が '' abbba bbb ''であるとします。 'abbba'はマップ内の何にもマッチしないので、そのまま文字列に残しておくべきだと思いますが、' str.replace() 'はそれを打ち消します。 – ajb

+0

@ajb、いいえ、それは正しくありません。私のコード_leaves_文字列の中には何も配置されていません。コードを慎重に読んだり、実行したりしなかった。 –

+0

私は 'str'の初期値を' 'abbba bbb" 'に置き換え、' pattern'を定義する行から無関係な "コンパイル"を取り除いて実行しました。結果: '' ajavaa java "'。 OPのコードを実行すると( 'replace!= null'のチェックを追加すると)、' 'abbba java" 'になります。だから、コードを慎重に読んだ。私は心の読書のスキルが疑わしいが、後者はOPが探しているものだと思う。 – ajb

1

をマップ内の一致がない場合は、mapping.get()はこのコードでnullを返します:

 String replace = mapping.get(matcher.group()); 
    matcher.appendReplacement(sb, replace + " "); 

あなたが期待していたことはわかりません。文字列が地図にない場合、コードではappendReplacementをスキップしたいと魔法のように知っていたようです。しかし、もちろん、コードは心を読むことができず、魔法のように動作しません。 replacenullの場合、プログラムは引き続き次の行を実行しようとします。

あなたが見ている結果は、+演算子が文字列でどのように動作するかに起因します。オペランドの1つがnullの場合、+は実際には4文字の文字列"null"を結果に挿入します。したがって、replace + " ""null "であり、コードでは、一致しない文字列がそのコードに置き換えられます。 (ただし、これは:

matcher.appendReplacement(sb, replace); 

にはNullPointerExceptionがあります。)

だから基本的に、あなたは何の一致がない場合は、交換をしないことをお伝えしたいと思いますし、この行うにはカップルの方法があります:のため

String replace = mapping.get(matcher.group()); 
if (replace != null) { 
    matcher.appendReplacement(sb, replace + " "); 
} 

または

if (mapping.containsKey(matcher.group())) { 
    String replace = mapping.get(matcher.group()); 
    matcher.appendReplacement(sb, replace + " "); 
} 

は、方法がappendReplacementの場合は、matcher.find()をスキップすると、matcherの追加位置には触れません。したがって、次回ループを通過するときに一致するものがあれば、それ以前の一致(マッピングのないもの)はその時点でコピーされます。または、ループから脱落した場合、以前の試合はappendTailでコピーされます。

しかし、あなたが書いたコードは、余分なスペースを結果に挿入しています。それがあなたが望むならば、次のappendにコピーするのではなく、マッピングがなくても余分なスペースを追加するように置換えを修正することができます。

効果で、あなたの例では "ddd ""ddd"に代わる
String replace = mapping.get(matcher.group()); 
if (replace == null) { 
    replace = matcher.group(); 
} 
matcher.appendReplacement(sb, replace + " "); 

。スペースをどのように扱うかを決める必要があります。たぶんあなたは本当に余分なスペースを望まなかったでしょうか? appendメソッドは、入力から入力されたテキストを、それらのスペース文字を含む一致するポイントまでコピーします。したがって、実際に結果のスペースの数を増やしたい場合を除いて、余分なスペースを含める必要はありません。

+0

あなたは、OPが世界を征服することができるものではなく、簡単な修正が欲しいという答えが受け入れられたことで分かります。私はあなたと再び会うことを楽しみにしています。 –

関連する問題