2016-07-06 128 views
1

我想打印不匹配的字符串,但結果爲空。如何打印不匹配字符串

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的空//我的預期「你好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

我只是運行它,用'「abbba bbb」'替換'str'的​​初始值,並從定義'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,程序仍然繼續並嘗試執行下一行。

您看到的結果是因爲+運算符如何處理字符串;如果其中一個操作數是null,則+實際上會將四個字符的字符串"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複製它。

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

這實際上將在你的榜樣取代"ddd"通過"ddd "。你必須決定如何處理這些空間。也許你真的不想要額外的空間?請記住,append方法會將輸入中的文本複製到匹配的點,包括那些空格字符。所以你真的不需要包含額外的空間,除非你真的想增加結果中的空格數。

+0

你可以看到,根據哪個答案被接受,OP想要一個簡單的修復,不一定能夠征服世界。我期待着與你再次互動。 –