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的主要内容,如果未能解决你的问题,请参考以下文章

java 解析json字符串

java 解析json字符串格式 []

java怎么使用gson解析json字符串

在java中解析一个xml字符串?

java实现解析二进制文件

java解析json字符串数据