Java流 - 两次分开字符串后获得结果



我有一个字符串:

String modulesToUpdate = "potato:module1, tomato:module2";

我只想从中获得:

module1
module2

首先,我必须用",然后用":"

将其分开

所以,我这样做了:

String files[] = modulesToUpdate.split(",");
for(String file: files){
    String f[] = file.split(":");
    for(int i=0; i<f.length; i++){
        System.out.println(f[1])
    }
}

这有效,但是循环中的循环并不优雅。

我试图用流进行同样的事情。

所以,我这样做了:

Stream.of(modulesToUpdate)
            .map(line -> line.split(","))
            .flatMap(Arrays::stream)
            .flatMap(Pattern.compile(":")::splitAsStream)
            .forEach(f-> System.out.println(f.toString().trim()));

输出:

potato
module1
tomato
module2

如何减少/过滤它才能获得:

module1
module2

更改一行:

  .map(x -> x.split(":")[1])

而不是:

  .flatMap(Pattern.compile(":")::splitAsStream)

或@holger在评论中提到:

 .map(s -> s.substring(s.indexOf(':')+1))

这根本不会创建中间数组。

flatMap正在返回Stream,而流则没有索引,但是在这种情况下,您确实需要它们才能到达第二个令牌。

split操作可以一次执行所有步骤。

考虑使用分离器模式,s*而不仅仅是,分开,以摆脱对随后的trim操作的需求。同样,我们可以将不需要的前缀(匹配的[^:]*?:(视为分离器的一部分,以删除它。

只剩下一件事;第一个元素的前缀不被视为分离器。我们可能会做,在流操作之前手动将其删除

Pattern.compile(",\s*[^:]*?:")
       .splitAsStream(modulesToUpdate.substring(modulesToUpdate.indexOf(':')+1))
       .forEach(System.out::println);

否则我们允许将字符串开始时的前缀作为分隔符对待,该分离器可以使拆分操作处理它,但在开始时会创建一个空字符串,我们必须跳过

Pattern.compile("(^|,\s*)[^:]*?:").splitAsStream(modulesToUpdate)
       .skip(1)
       .forEach(System.out::println);

您可以在flatMap内使用skip,例如:

String modulesToUpdate = "potato:module1, tomato:module2";
Arrays.stream(modulesToUpdate.split(","))
.map(String::trim)
.flatMap(s -> Arrays.stream(s.split(":")).skip(1))
.forEach(System.out::println);

也许另一个选项可以是:

  1. 分开到多个条件
  2. 流式阵列并在奇数位置收集元素

String modulesToUpdate = "potato:module1, tomato:module2";
String[] mod = modulesToUpdate.split("[:,]");
List<String> res = IntStream.range(0, mod.length)
                     .filter(j -> (j % 2) == 0)
                     .mapToObj(i -> mod[i])
                     .collect(Collectors.toList());
System.out.println(res);

最新更新