哪个字符串方法更好用:“contains”还是“indexOf > -1”?

59

以下哪种方式是确定子字符串包含的有效方式?

if (str.indexOf("/") > -1)
或者
if (str.contains("/")) 

3
我不关注效率,但为了代码清晰度,我更喜欢使用contains()函数。 - nhahtdh
8个回答

117

看一下java.lang.String源代码,contains方法是用indexOf实现的,因此它们本质上是相同的。

public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

你应该使用使代码更易读的方法。如果你要检查一个字符串是否包含特定子串,请使用 contains 。如果你要查找子串的起始索引,请使用 indexOf


编辑:

有几个答案提到应该优先选择 indexOf,因为 contains 进行了额外的方法调用,因此效率较低。这是错误的。在这种情况下,由于额外的方法调用造成的开销完全可以忽略不计。请根据你的实现上下文使用最合适的方法,以使你的代码更易读。


14
在这种情况下,由于额外方法调用所引起的开销是完全微不足道的。这是因为字节码优化等原因导致的。对于普通人来说,似乎调用堆栈上的额外层次会产生一些影响。但事实上,由于现代编译器的优化措施,在大多数情况下,这种影响是可以忽略不计的。 - jtravaglini
4
额外的方法调用并不一定是无足轻重的。我猜你认为JIT编译器会将其内联,但这并不是有保证的,而且并非所有的Java编译器都使用JIT编译。因此,“这是错误的”的简单声明是错误的。 - Will Calderwood
1
直接搜索字符 '' 怎么样?因为 contains 会执行 toString - Tupac
正如上面所解释的,这个问题没有意义,是的。但为了代码清晰度,我更喜欢使用contains,但如果我们需要“第一次出现的索引”,那么就会使用indexOf。 - Asraful
如果我们在一个超过一百万次重复的循环中使用 "if (str.contains("/"))" 会怎样? - Arash

29

我认为在回答这个问题时,最好采用经验主义方法,而不是猜测额外方法调用的开销会如何影响结果。我使用了这个答案中的 indexOf基准测试,并添加了两个contains()基准测试方法(一个使用字符串常量,另一个使用变量)。我正在运行新发布的 Windows x64 1.8.0_71。

# JMH 1.11.3 (released 8 days ago)
# VM version: JDK 1.8.0_71, VM 25.71-b15

Benchmark                           Mode  Cnt   Score   Error  Units
IndexOfTest.containsString          avgt   30  26.596 ± 0.099  ns/op
IndexOfTest.containsStringIndirect  avgt   30  28.683 ± 0.088  ns/op
IndexOfTest.indexOfChar             avgt   30  26.855 ± 0.171  ns/op
IndexOfTest.indexOfCharIndirect     avgt   30  25.833 ± 0.116  ns/op
IndexOfTest.indexOfString           avgt   30  26.192 ± 0.107  ns/op
IndexOfTest.indexOfStringIndirect   avgt   30  27.547 ± 0.152  ns/op

请注意,基准测试测量的是每个操作的纳秒数。因此,比较 contains("z") 和 indexOf("z"),indexOf() 的速度略微更快,但仅快了不到 0.6 纳秒。有趣的是,间接方式(使用变量)具有大约 1 纳秒的差异。

我已将此基准测试的代码放在 GitHub 上:https://github.com/tedyoung/indexof-contains-benchmark


7

如果目标是确定一个字符串是否包含另一个字符串,那么contains()方法是明显的赢家。这将使其他开发人员更有效地理解您的意图。


3

基本上它们两个是相同的。

public boolean contains(CharSequence s) {
    return indexOf(s.toString()) > -1;
}

如果您想通过索引做某事,可以使用indexOf

我相信indexOf会更加高效,但是差异可以忽略不计。


2

对于单个字符搜索,如果indexOf的参数是一个char,则效率更高:

if (str.indexOf('/') > -1)

2

虽然使用str.contains("/")更易读,但使用str.indexOf('/') > -1可能更有效率。请注意,在indexOf调用中我使用了字符而不是字符串。

但除非你在一个非常紧密的循环中,否则这并不会对性能产生太大影响。


2

这些方法有不同的用途,如果你需要检查字符串是否包含某个字符或子串,则使用contains方法;但是如果你想知道它在字符串中的位置,则使用indexOf方法。


1

最近我使用indexOf()时遇到了一个问题:当试图查找字符串中是否包含空格以将其替换为其他内容时,IndexOf的答案是:该字符串没有空格,这是错误的答案。当使用Contains()替换后,答案是正确的。因为正如一些人在这里所说的那样,Contains()会调用IndexOf


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接