我有一个字符串:
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);
也许另一个选项可以是:
- 分开到多个条件
- 流式阵列并在奇数位置收集元素
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);