【问题标题】:String manipulation in Java 8 StreamsJava 8 Streams 中的字符串操作
【发布时间】:2016-03-15 05:47:20
【问题描述】:

我有一个字符串流,例如- Token1:Token2:Token3 这里':' 是分隔符。这里Token3 字符串可能包含分隔符,也可能不存在。 我们必须将此流转换为以 Token1 作为键的映射,值是两个字符串的数组——array[0] = Token2array[1] = Token3 如果存在Token3,否则为null。 我尝试过类似的东西-

return Arrays.stream(inputArray)
            .map( elem -> elem.split(":"))
            .filter( elem -> elem.length==2 )
            .collect(Collectors.toMap( e-> e[0], e -> {e[1],e[2]}));

但它没有用。除此之外,如果 Token3 不存在或其中包含分隔符,它不处理这种情况。

如何在 Java8 lambda 表达式中完成它?

【问题讨论】:

    标签: java string lambda java-8 java-stream


    【解决方案1】:

    您可以将每个输入字符串映射到正则表达式Matcher,然后只保留那些实际匹配的字符串,并使用Matcher.group() 方法通过toMap 收集器收集:

    Map<String, String[]> map = Arrays.stream(inputArray)
        .map(Pattern.compile("([^:]++):([^:]++):?(.+)?")::matcher)
        .filter(Matcher::matches)
        .collect(Collectors.toMap(m -> m.group(1), m -> new String[] {m.group(2), m.group(3)}));
    

    全面测试:

    String[] inputArray = {"Token1:Token2:Token3:other",
            "foo:bar:baz:qux", "test:test"};
    Map<String, String[]> map = Arrays.stream(inputArray)
        .map(Pattern.compile("([^:]++):([^:]++):?(.+)?")::matcher)
        .filter(Matcher::matches)
        .collect(Collectors.toMap(m -> m.group(1), m -> new String[] {m.group(2), m.group(3)}));
    map.forEach((k, v) -> {
        System.out.println(k+" => "+Arrays.toString(v));
    });
    

    输出:

    test => [test, null]
    foo => [bar, baz:qux]
    Token1 => [Token2, Token3:other]
    

    String.split 也可以解决同样的问题。您只需要使用双参数拆分版本并指定您最多希望拥有多少个部分:

    Map<String, String[]> map = Arrays.stream(inputArray)
        .map(elem -> elem.split(":", 3)) // 3 means that no more than 3 parts are necessary
        .filter(elem -> elem.length >= 2)
        .collect(Collectors.toMap(m -> m[0], 
                                  m -> new String[] {m[1], m.length > 2 ? m[2] : null}));
    

    结果是一样的。

    【讨论】:

    • 在 lambda 表达式中给出错误-错误返回类型的解决方案:字符串无法转换为字符串 []
    • @Abhijeetsrivastava 你确定你的方法的返回值是Map&lt;String, String[]&gt;吗?现在可能是Map&lt;String, String&gt;
    【解决方案2】:

    您可以通过以下方式实现您想要的:

        return Arrays.stream(inputArray)
                .map(elem -> elem.split(":", 3)) // split into at most 3 parts
                .filter(arr -> arr.length >= 2)  // discard invalid input (?)
                .collect(Collectors.toMap(arr -> arr[0], arr -> Arrays.copyOfRange(arr, 1, 3)));  // will add null as the second element if the array length is 2
    

    【讨论】:

      猜你喜欢
      • 2015-03-08
      • 2014-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-27
      • 2018-03-26
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多