【问题标题】:appending a string with matching values from key of map in java8 steam在java 8流中从map的键中附加一个匹配值的字符串
【发布时间】:2021-06-20 19:37:24
【问题描述】:

我有一个字符串列表和 Map 如果元素列表与地图的关键元素匹配,我需要用地图的值替换字符串的值。

List<String> mylist = Arrays.asList("key1", "key2", "key3", "key4");
Map<String, String> map2 = new HashMap<>();
map2.put("key1", "value1");
map2.put("key2", "value2");
map2.put("key11", "value11");
var classVar = new Object() {
    String sb = "";
};
classVar.sb = "Select * from table1 where key1='apple' and key2='mango' and key11='banana'";

mylist.forEach(e -> {
    map2.forEach((k, v) -> {
        if (e.equalsIgnoreCase(k)) {
            classVar.sb = classVar.sb.replaceAll(k, v);
        }
    });
});

最后的字符串应该是:

Select * from table1 where value1='apple' and value2='mango' and key11='banana'

Key11 不应被替换,因为它不在 mylist 中。

如何使用 Java 8 的 map()/stream() 等功能而不是 forEach 循环来做同样的事情?我在列表和映射中有大量字符串元素,我需要在最终字符串中动态替换它们。

【问题讨论】:

  • 看起来您正在从某个地方收到的纯非参数化字符串构建 SQL 语句。如果你还不知道,你可能想了解一下 SQL 注入
  • 你已经在这里问过这个问题:stackoverflow.com/questions/68053753/…
  • 这能回答你的问题吗? how to iterate a map to replace in final string
  • 我已经尝试了上面链接中的解决方案。位我无法将我的字符串设为 AtomicReference。 Stream.reduce() 示例代码不起作用..任何人都可以建议如何在这种情况下成功使用 stream.reduce()

标签: java java-stream


【解决方案1】:

试试这个。

List<String> mylist = Arrays.asList("key1", "key2", "key3", "key4");
Set<String> mylistLower = mylist.stream().map(String::toLowerCase).collect(Collectors.toSet());
Map<String, String> map2 = new HashMap<String, String>();
map2.put("key1", "value1");
map2.put("key2", "value2");
map2.put("key11", "value11");
String in = "Select * from table1 where key1='apple' and key2='mango' and key11='banana'";
String out = Pattern.compile(map2.keySet().stream()
    .filter(s -> mylistLower.contains(s.toLowerCase()))
    .map(s -> "\\b" + Pattern.quote(s) + "\\b")
    .collect(Collectors.joining("|")))
    .matcher(in)
    .replaceAll(m -> map2.get(m.group()));
System.out.println(out);

输出:

Select * from table1 where value1='apple' and value2='mango' and key11='banana'

或者你也可以这样做。

String out = map2.entrySet().parallelStream()
    .filter(e -> mylistLower.contains(e.getKey().toLowerCase()))
    .reduce(in, (s, e) -> s.replaceAll("\\b" + e.getKey() + "\\b", e.getValue()),
        (a, b) -> a);

【讨论】:

  • 可以请任何人建议如何使用 map.reduce() 做同样的事情
【解决方案2】:
Set<String> keys = Set.of("key1", "key2", "key3", "key4");
Map<String, String> map = Map.of(
        "key1", "value1",
        "key2", "value2",
        "key11", "value11");
String sql = "Select * from table1 where key1='apple' and key2='mango' and key11='banana'";
String res = Arrays.stream(sql.split("\\b"))
                   .map(word -> keys.contains(word) ? map.getOrDefault(word, word) : word)
                   .collect(Collectors.joining());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 1970-01-01
    相关资源
    最近更新 更多