Java 如何将字符串拆分为字符串流?
将字符串拆分为流的最佳方法是什么 我看到了这些变化:Java 如何将字符串拆分为字符串流?,java,regex,split,java-stream,Java,Regex,Split,Java Stream,将字符串拆分为流的最佳方法是什么 我看到了这些变化: Arrays.stream(“b,l,a”.split(“,”) Stream.of(“b,l,a.”分割(“,”) Pattern.compile(“,”).splitAsStream(“b,l,a”) 我的优先事项是: 健壮性 可读性 演出 完整的、可编译的: 导入java.util.array; 导入java.util.regex.Pattern; 导入java.util.stream.stream; 公共类HelloWorld{
Arrays.stream(“b,l,a”.split(“,”)
Stream.of(“b,l,a.”分割(“,”)
Pattern.compile(“,”).splitAsStream(“b,l,a”)
- 健壮性
- 可读性
- 演出
导入java.util.array;
导入java.util.regex.Pattern;
导入java.util.stream.stream;
公共类HelloWorld{
公共静态void main(字符串[]args){
stream1().forEach(System.out::println);
stream2().forEach(System.out::println);
stream3().forEach(System.out::println);
}
私有静态流stream1(){
返回Arrays.stream(“b,l,a”.split(“,”);
}
私有静态流stream2(){
返回流。of(“b,l,a”。拆分(“,”);
}
私有静态流stream3(){
返回模式.compile(“,”).splitAsStream(“b,l,a”);
}
}
关于(1)和(2)应该没有太大区别,因为您的代码几乎相同。关于(3),就内存而言(不一定是CPU),这将更有效,但在我看来,更难阅读。
Arrays.stream
/String.split
由于返回数组String[]
,因此我始终建议将Arrays.stream
作为通过数组进行流式处理的标准用法
String input = "dog,cat,bird";
Stream<String> stream = Arrays.stream(input.split( "," ));
stream.forEach(System.out::println);
Pattern.splitAsStream
具有直接流式传输而不是创建中间阵列的优势。因此,对于大量的子字符串,这会带来性能上的好处。另一方面,如果分隔符很简单,即单个文字字符,String.split
实现将通过一条快速路径,而不是使用正则表达式引擎。因此,在这种情况下,答案并非微不足道
Stream<String> stream = Pattern.compile(",").splitAsStream(input);
这是expression::name
形式的方法引用的属性,它将在创建函数接口实例时计算表达式并捕获结果,如和中所述
健壮性
我看不出这三种方法的稳健性有什么不同
可读性
我不知道有经验的Java程序员对代码可读性进行过任何可信的科学研究,所以可读性是一个意见问题。即便如此,你也永远不知道,如果有人给出自己的观点,是否在实际可读性、他们所学的可读性以及他们自己的品味之间做出了客观的区分
所以我会让你自己对可读性做出判断。。。注意到你认为这是一个高优先级。
FWIW,唯一对这件事有意见的人是你和你的团队
演出
我认为解决这个问题的办法是仔细衡量这三个备选方案。Holger根据他对一些Java版本的研究提供了一个分析。但是:
流
对象所做的操作、您选择的垃圾收集器(因为不同版本显然会产生不同数量的垃圾)以及其他问题所以,如果您(或任何其他人)真的关心性能,您应该编写一个微基准测试,并在您的生产平台上运行它。然后做一些特定于应用程序的基准测试。你应该考虑看那些不涉及流的解决方案。你认为有这么大的差别,花时间去琢磨“最好”的方法是有意义的,或者你认为这是你的程序中的一个性能热点,使它至少有点合理,试图找到“最好的”。方法?请注意,
Stream.of()
将在内部调用Arrays.Stream()
,显然这不是“最好的”。嗯,最后一个才是最好的。没有嵌套的paren,很明显它是关于regex的,并且它不会创建所有段的中间列表或数组。但那只是我的意见.我认为我们不能特别判断他想知道这些信息的理由。虽然“最好”是一种观点,但你的意思是“最快”吗?@Prospero OP清楚地阐明了他所追求的:健壮性、可读性和性能。.flatMap(Pattern.compile(Pattern)
为什么模式只需分析一次?是否存在缓存?如果是,这是否写在文档中的某个地方?@Roland:这是表达式::名称形式的方法引用的一个属性,表达式将被计算,并由创建的函数实例捕获结果。使用模式.compile(模式)::splitAsStream
,表达式是Pattern.compile(Pattern)
。这与Pattern.compile(Pattern)根本不同。splitAsStream(string)
将在每次函数求值时重新计算模式。请参见和…@Benj问题是它甚至调用了子序列(…).toString()
,因此使用不同的CharSequence
实现(即非复制)只会将复制推迟到后续的toString()
调用。但对于标记化,您更希望使用Java 9的Matcher.results()
或Scanner.findAll(…)无论如何,请考虑后备。因为<代码> MatcRESULTS/<代码>提供<代码>开始()(代码)>和<代码>结束()/代码>,您可以在ApOP的基础上构建无拷贝操作。
Stream<String> stream = Stream.of(input.split(",")); // works, but is non-idiomatic
Stream<String> stream = Stream.of("dog", "cat", "bird"); // intended use case
Stream<String> stream = Pattern.compile(",").splitAsStream(input);
Stream<String> stream = Stream.of("a,b", "c,d,e", "f", "g,h,i,j")
.flatMap(Pattern.compile(",")::splitAsStream);