Java 8流中的字符串操作

4

我有一个字符串流,格式如下: Token1:Token2:Token3 这里的':'是分隔符。这里的Token3字符串可能包含分隔符或者不存在。 我们需要将这个流转换成一个map,其中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表达式实现呢?

2个回答

6
你可以将每个输入字符串映射到正则表达式的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表达式中的返回类型错误:无法将String转换为String[]。 - Abhijeet srivastava
1
@Abhijeetsrivastava 你确定你的方法返回值是 Map<String, String[]> 吗?可能现在应该是 Map<String, String> - Tagir Valeev

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接