簡體   English   中英

使用hashmap值替換String get Error

[英]Use hashmap value to replace String get Error

我有一個String"abc|a&b" ),我想更換的零件String與其他String秒。 替換項存儲在HashMap<String, String>中,如下所示:

  1. "a" > "true"
  2. "b" > "false"
  3. "abc" > "true"

我的結果是"truefalsec|true&false" ,但是我需要"true|true&false"

我的代碼:

for(Map.Entry<String, String> entry: map.entrySet()) {
    if(expression.contains(entry.getKey()))
        expression = expression.replace(entry.getKey(), entry.getValue());
}
System.out.println(expression);

你們有什么建議嗎?

    String expression = "abc|a&b";

    Map<String, String> map = new LinkedHashMap<>();

    map.put("a", "true");
    map.put("abc", "true");
    map.put("b", "false");

    List<String> parts = Arrays.stream(expression.split("\\W+")).filter(map::containsKey)
            .map(map::get).collect(Collectors.toList());

    Queue<String> separators = new LinkedList<>(Arrays.asList(expression.split("\\w+"))
            .stream().filter(s -> !s.isEmpty())
            .collect(Collectors.toList()));

    StringBuilder result = new StringBuilder();

    for(String part : parts){
        result.append(part).append(!separators.isEmpty() ? separators.poll() : "");
    }

    System.out.println(result.toString());

您可以使用流從表達式中獲取所有鍵,然后對分隔符使用相同的鍵->更改所需內容,然后將整個內容合並回String。

問題是您重新開始掃描以進行下一個替換,並且首先掃描了最短的輸入。

通過掃描a之前的abc ,您將永遠不會匹配abc ,因為在掃描abc之前a已經被別的東西替代了。 按照rgettman的評論,對要掃描的部分按長度進行排序,以最長的為准

通過重新啟動每個輸入的掃描,您可以替換替換值的內容。 例如,如果您掃描bab被換成false ,但隨后的afalse被替換為true ,導致b開始替換ftruelse

要解決第二個問題並提高性能,您應該只掃描一次輸入。

掃描輸入一次(掃描多個文本之一)的最簡單方法是使用正則表達式,例如abc|a|b ,即列出用|分隔的鍵| ,最長的鍵在前。

假設替換映射可以是任何東西,您應該從Map動態構建正則表達式,記住要在Map同時引用鍵和值,因此任何特殊字符都不會被視為正則表達式特殊字符,例如match-任何字符.

這是使用regex替換循環執行所有操作的方法(在Java 8中):

public static String replace(String input, Map<String, String> replacementValues) {
    String regex = replacementValues.keySet().stream()
                   .sorted(Comparator.comparingInt(String::length).reversed()
                                     .thenComparing(Function.identity()))
                   .map(Pattern::quote)
                   .collect(Collectors.joining("|"));
    StringBuffer buf = new StringBuffer(input.length() + 16);
    Matcher m = Pattern.compile(regex).matcher(input);
    while (m.find())
        m.appendReplacement(buf, Matcher.quoteReplacement(replacementValues.get(m.group())));
    return m.appendTail(buf).toString();
}

測試

Map<String, String> map = new HashMap<>();
map.put("a", "true");
map.put("b", "false");
map.put("abc", "true");
System.out.println(replace("abc|a&b", map));

輸出量

true|true&false


如果掃描應匹配單詞而不是子字符串,請將正則表達式編譯更改為:

Pattern.compile("\\b(?:" + regex + ")\\b")

問題是,您首先要替換ab 然后,不會保留abc ,也不會被替換。 您可以使用LinkedHashMap並按希望替換的順序插入元素。這是LinkedHashMap ,因為LinkedHashMap允許您按插入順序迭代其值,而HashMap會按順序返回它們取決於鍵hashCode

Map<String, String> map = new LinkedHashMap<>();
map.put("abc", "true");
map.put("a", "true");
map.put("b", "false");

for(Map.Entry<String, String> entry: map.entrySet()) {
    expression = expression.replace(entry.getKey(), entry.getValue());
}
System.out.println(expression);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM