Java - 解析字符串 - String.split() 与 Pattern & Matcher
Posted
技术标签:
【中文标题】Java - 解析字符串 - String.split() 与 Pattern & Matcher【英文标题】:Java - Parsing strings - String.split() versus Pattern & Matcher 【发布时间】:2014-09-08 21:48:21 【问题描述】:给定一个包含逗号分隔列表的字符串,表示专有名词和类别/描述对,使用 String.split() 与 Pattern & Matcher 方法查找特定专有名词并提取相关类别的优缺点是什么/描述对?
haystack 字符串格式不会改变。它将始终包含逗号分隔的数据,形式为 PROPER_NOUN|类别/描述
两种方法的共同变量:
String haystack="EARTH|PLANET/COMFORTABLE,MARS|PLANET/HARDTOBREATHE,PLUTO|DWARF_PLANET/FARAWAY";
String needle="PLUTO";
String result=null;
使用 String.split():
for (String current : haystack.split(","))
if (current.contains(needle))
result=current.split("\\|")[1]);
break; // *edit* Not part of original code - added in response to comment from Pshemo
使用模式和匹配器:
Pattern pattern = pattern.compile("(" +needle+ "\|)(\w+/\w+)");
Matcher matches = pattern.matcher(haystack);
if (matches.find())
result=matches.group(2);
这两种方法都提供了我需要的信息。
我想知道是否有任何理由选择其中之一。我目前没有在我的项目中使用 Pattern & Matcher,所以这种方法需要从 java.util.regex
导入当然,如果有客观上“更好”的方法来解析信息,我将欢迎您的意见。
感谢您的宝贵时间!
结论
我选择了模式/匹配器方法。虽然使用正则表达式读取有点棘手,但它比 .split()/.contains()/.split() 更快,而且对我来说更重要的是,它只捕获第一个匹配项。
不管怎样,这是我不完美的基准测试的结果,以纳秒为单位,经过 100,000 次迭代:
.split()/.contains()/.split
304,212,973
Pattern/Matcher w/Pattern.compile() 为每次迭代调用
230,511,000
Pattern/Matcher w/Pattern.compile() 在迭代之前调用
111,545,646
【问题讨论】:
只是一个小评论:如果您是根据用户输入手动构建模式,请始终使用Pattern.quote()
转义字符串。
Pattern/Matcher
解决方案的唯一优点是它会在找到 needle|\w+/\w+
时停止迭代您的输入,而 split(",")
将迭代整个输入,然后再次迭代,直到找到 sting包含needle
。我不确定contains
是否是正确的方法,除非您确定搜索到的noun
永远不会作为category/description
对的一部分出现。
@biziclop:感谢 .quote() 提示,我不知道这种方法。
@Pshemo:非常感谢您的 contains() 标注。不应该有重复的名词,但我和其他人一起工作,我们倾向于远离无误。如果我使用 .split() 路线,我将包含一个 'break;'
请注意,您的两个实现在某些输入字符串上的行为不同。例如,如果针出现在|
的右侧,或者如果左侧不包含/
,则基于String.split()
的实现将接受它,但不会接受Pattern
实现。跨度>
【参考方案1】:
在这样的小情况下,这并不重要。但是,如果您有非常大的字符串,直接使用 Pattern/Matcher 可能会有好处。
大多数使用正则表达式的字符串函数(如matches()、split()、replaceAll()等)直接使用Matcher/Pattern。因此每次都会创建一个 Matcher 对象,在大循环中使用时会导致效率低下。
因此,如果你真的想要速度,你可以直接使用 Matcher/Pattern,理想情况下只创建一个 Matcher 对象。
【讨论】:
感谢新兹!这个答案抓住了我一直在寻找的东西,并且简洁地做到了。 +1 @Pshemo,不过,因为我实现 contains() 的方式可能存在缺陷。【参考方案2】:在操作如此简单的情况下,使用模式/匹配器没有优势。
您可以将String.split()
视为一种方便的方法,它利用了您在直接使用模式/匹配器时使用的许多相同功能。
当您需要进行更复杂的匹配/操作时,请使用模式/匹配器,但是当String.split()
满足您的需求时,使用它的明显优势是它大大降低了代码复杂度——我认为没有什么好处有理由将这一优势传递出去。
【讨论】:
【参考方案3】:我想说split()
版本在这里要好得多,原因如下:
split()
代码非常清晰,很容易看出它的作用。正则表达式版本需要更多分析。
正则表达式更复杂,因此代码更容易出错。
【讨论】:
我完全同意 .split()/.contains()/.split() 是这两个选项中更易读的,并且有些人是 regexaphobes & 看看 regex 的使用如何导致问题。不过,我对你的第三点有点不确定。在阅读了@Xinzz 的答案后,我运行了一些非常基本的基准测试,并且 Pattern/Matcher 更快,即使实例化了多个 Matcher 对象。就成本而言,您是指 CPU 使用率吗? @Idus:你可能是对的。这个我想多了一点,第三点应该去掉。无论如何,这是最不重要的考虑因素。String.split()
的参数也是一个正则表达式。以上是关于Java - 解析字符串 - String.split() 与 Pattern & Matcher的主要内容,如果未能解决你的问题,请参考以下文章