Hos*_*ein 7 java-8 java-stream
我想在一个字符串上执行多个任务.我需要使用分隔符("/")获取一个字符串并提取不同的子字符串,然后反转子字符串列表,最后使用另一个分隔符(".")/tmp/test/hello/world/将它们连接起来,这样就会变成:world.hello.test.tmp
使用Java 7代码如下:
String str ="/tmp/test/";
List<String> elephantList = new ArrayList<String>(Arrays.asList(str.split("/")));
StringBuilder sb = new StringBuilder();
for (int i=elephantList.size()-1; i>-1; i--) {
String a = elephantList.get(i);
if (a.equals(""))
{
elephantList.remove(i);
}
else
{
sb.append(a);
sb.append('.');
}
}
sb.setLength(sb.length() - 1);
System.out.println("result" + elephantList + " " + sb.toString());
Run Code Online (Sandbox Code Playgroud)
我想知道如何使用Java 8流和它对字符串的连接功能做同样的事情
Mis*_*sha 10
最直接的方法是将术语收集到列表中,反转列表并加入新的分隔符:
import static java.util.stream.Collectors.toCollection;
List<String> terms = Pattern.compile("/")
.splitAsStream(str)
.filter(s -> !s.isEmpty())
.collect(toCollection(ArrayList::new));
Collections.reverse(terms);
String result = String.join(".", terms);
Run Code Online (Sandbox Code Playgroud)
你可以在不收集中间列表的情况下完成它,但它的可读性较差,不值得为实际目的而烦恼.
要考虑的另一个问题是您的字符串似乎是路径.通常最好使用Path类而不是手动分割"/".以下是您将如何执行此操作(此方法还演示了如何使用IntStreamover索引向后流式传输列表):
Path p = Paths.get(str);
result = IntStream.rangeClosed(1, p.getNameCount())
.map(i -> p.getNameCount() - i) // becomes a stream of count-1 to 0
.mapToObj(p::getName)
.map(Path::toString)
.collect(joining("."));
Run Code Online (Sandbox Code Playgroud)
这将具有独立于操作系统的优点.
如果您不需要中间列表,而只想String反向加入:
String delimiter = ".";
Optional<String> result = Pattern.compile("/")
.splitAsStream(str)
.filter(s -> ! s.isEmpty())
.reduce((s, s2) -> String.join(delimiter, s2, s));
Run Code Online (Sandbox Code Playgroud)
或者只是使用.reduce((s1, s2) -> s2 + '.' + s1);它可能具有的可读性String.join(".", s2, s1);(感谢Holger的建议)。
从那时起,您可以执行以下任一操作:
result.ifPresent(System.out::println); // print the result
String resultAsString = result.orElse(""); // get the value or default to empty string
resultAsString = result.orElseThrow(() -> new RuntimeException("not a valid path?")); // get the value or throw an exception
Run Code Online (Sandbox Code Playgroud)
使用StreamSupport和的另一种方式Spliterator(受Mishas建议使用的启发Path):
Optional<String> result = StreamSupport.stream(Paths.get(str).spliterator(), false)
.map(Path::getFileName)
.map(Path::toString)
.reduce((s, s2) -> s2 + '.' + s);
Run Code Online (Sandbox Code Playgroud)
当然,您可以通过省略中间对象来简化它,Optional而只需立即调用所需的方法即可:
stream(get(str).spliterator(), false)
.map(Path::getFileName)
.map(Path::toString)
.reduce((s, s2) -> s2 + '.' + s)
.ifPresent(out::println); // orElse... orElseThrow
Run Code Online (Sandbox Code Playgroud)
在上一个示例中,您将添加以下静态导入:
import static java.lang.System.out;
import static java.nio.file.Paths.get;
import static java.util.stream.StreamSupport.stream;
Run Code Online (Sandbox Code Playgroud)