在Java中正确使用流

时间:2019-04-15 15:30:42

标签: java optimization java-8 java-stream

我有一个用例,需要解析键值对(用=分隔)并将这些键值对放在LinkedHashMap中。

我想忽略以下类型的String

  • 键为空或仅包含空格
  • 值为空或仅包含空格
  • 这些String不包含=

现在,我已经使用命令式样式和流方法解决了它。

以下是2个变体:

通过迭代样式的解决方案-for循环和大量if

public static Map<String, String> getMap1(String[] array) {
    Map<String, String> map = new LinkedHashMap<>();
    for (int i = 0; i < array.length; i++) {
        String currentString = array[i];
        int index = currentString.indexOf('=');

        // ignoring strings that don't contain '='
        if (index == -1) continue;
        String key = currentString.substring(0, index).trim();
        String value = currentString.substring(index + 1).trim();

        // ignoring strings with empty key or value
        if (key.length() == 0 || value.length() == 0) continue;

        map.put(key, value);
    }
    return map;
}

使用Stream s的解决方案-非常简洁的代码

public static Map<String, String> getMap(String[] array) {
    return Arrays.stream(array)
            .filter(s -> s.indexOf('=') != -1) // ignore strings that don't contain '='
            .filter(s -> s.substring(0, s.indexOf('=')).trim().length() != 0) // key should be present
            .filter(s -> s.substring(s.indexOf('=') + 1).trim().length() != 0) // value should be present
            .collect(Collectors.toMap(
                    s -> s.substring(0, s.indexOf('=')).trim(),
                    s -> s.substring(s.indexOf('=') + 1).trim(),
                    (first, second) -> second,
                    LinkedHashMap::new));

}

我在这里担心,因为在使用Stream时,我多次调用indexOf方法。 (对于大字符串,我可以一次又一次地重新计算同一件事。)

有没有一种方法可以避免通过indexOf方法进行重新计算,从而使代码仍然干净。 (我知道谈论干净代码是非常主观的,但是我不想打开多个流,通过原始字符串数组进行循环,然后预先计算=的索引,然后重新使用)。

再次将多个filter合并到一个过滤器中似乎是一种选择,但这会使我的谓词非常难看。

(这是我想学习/改善的无所事事的结果)。

2 个答案:

答案 0 :(得分:3)

那呢:

 String[]  array = {"aaa2=asdas","aaa=asdasd"};

    LinkedHashMap<String, String> aaa = Arrays.stream(array)
            .map(s -> s.split("=", 2))
            .filter(s -> s.length == 2) // ignore strings that don't contain '='
            .peek(s -> { s[0] = s[0].trim(); })
            .peek(s -> { s[1] = s[1].trim(); })
            .filter(s -> s[0].length() != 0) // key should be present
            .filter(s -> s[1].length() != 0) // value should be present
            .collect(Collectors.toMap(
                    s -> s[0],
                    s -> s[1],
                    (first, second) -> second,
                    LinkedHashMap::new));

答案 1 :(得分:0)

我将使用split而不是indexOf和StringUtils来检查您的键和值是否为空。

 public static Map<String, String> getMap(String[] array) {
        return Arrays.stream(array)
                .filter(s -> s.contains("="))
                .map(s -> s.split("="))
                .filter(s -> s.length == 2 && isNotBlank(s[0]) && isNotBlank(s[1]))
                .collect(Collectors.toMap(
                        s -> s[0].trim(),
                        s -> s[1].trim()));
    }