Java中与C#的“Enumerable.Any”等效的方法是什么?

28

在 C# 中可以使用 Enumerable.Any 来检查序列中是否存在满足条件的元素,从而减少 if 语句的长度(https://msdn.microsoft.com/zh-cn/library/system.linq.enumerable.any(v=vs.110).aspx)。

例如,不要写成:

If ( string.Contains(">") || string.Contains("<") || string.Contains("&") || string.Contains("l") || string.Contains("p") )

我们可以使用

if (new [] { ">", "<", "&", "l", "p"}.Any(w => string.Contains(w)))

在Java中是否有相等或更好的方法来做这件事?


1
仅为完整起见:在C#中,您还可以使用.Any(string.Contains)而不是更冗长的.Any(w => string.Contains(w)) - Bob
4个回答

26

使用Java 8,您可以编写类似以下内容的代码:

if (Stream.of(">", "<", "&", "l", "p").anyMatch(string::contains)) {
  ...
}

出于好奇心,我进行了一项基准测试,比较了这种方法和正则表达式的性能。以下是代码和结果(得分越低表示速度越快)。与正则表达式相比,流表现优秀一个数量级。

Benchmark                                    (s)  Mode  Samples     Score    Error  Units
c.a.p.SO30940682.stream   >aaaaaaaaaaaaaaaaaaaaa  avgt       10    49.942 ±  1.936  ns/op
c.a.p.SO30940682.stream   aaaaaaaaaaaaaaaaaaaaa>  avgt       10    54.263 ±  1.927  ns/op
c.a.p.SO30940682.stream   aaaaaaaaaaaaaaaaaaaaap  avgt       10   131.537 ±  4.908  ns/op
c.a.p.SO30940682.stream   paaaaaaaaaaaaaaaaaaaaa  avgt       10   129.528 ±  7.352  ns/op
c.a.p.SO30940682.regex    >aaaaaaaaaaaaaaaaaaaaa  avgt       10   649.867 ± 27.142  ns/op
c.a.p.SO30940682.regex    aaaaaaaaaaaaaaaaaaaaa>  avgt       10  1047.122 ± 89.230  ns/op
c.a.p.SO30940682.regex    aaaaaaaaaaaaaaaaaaaaap  avgt       10  1029.710 ± 61.055  ns/op
c.a.p.SO30940682.regex    paaaaaaaaaaaaaaaaaaaaa  avgt       10   694.309 ± 32.675  ns/op

代码:

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
public class SO30940682 {

  @Param({">aaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaa>",
          "aaaaaaaaaaaaaaaaaaaaap", "paaaaaaaaaaaaaaaaaaaaa"}) String s;

  @Benchmark public boolean stream() {
    return Stream.of(">", "<", "&", "l", "p").anyMatch(s::contains);
  }

  @Benchmark public boolean regex() {
    return s.matches("^.*?(>|<|&|l|p).*$");
  }
}

2
我的错,我删除了注释。我忽略了string是一个变量的事实。 - Marco Acierno
谢谢澄清。我想知道使用正则表达式检查子字符串是否比单个字符更快。我不确定 contains() 在这些情况下的性能如何。 - Srini
1
谢谢。这是一个完美的解决方案。如果人们没有使用JAVA 8,Bruce Wayne使用正则表达式的解决方案可能会很有用。 - Mirodinho
如果你真的想要速度并且只检查单个字符,那么你需要在字符串中的所有字符上使用单个循环来检查所有少量字符。我想知道与其他方法相比,这样做会快多少... - AlexR
哦,Java:\。抱歉,我忘记了那个方法是做什么的。但是如果你在正则表达式中看到两个.*,几乎可以肯定这个正则表达式是错误的,并且会非常慢。 - abc667
显示剩余3条评论

9

使用Java 8,可以使用anyMatch方法实现这一点:

if (Stream.of(">", "<", "&", "l", "p").anyMatch(w -> string.contains(w))) {

}

7

6
如果您没有Java 8,可以使用正则表达式来完成您的任务。 string.matches("^.*?(<|>|p|1|&).*$")就可以解决问题。
编辑:我想知道哪个解决方案更快。尽管JIT可以内联所有lambda好处,但是Stream(s)可能比使用正则表达式要慢。我可能完全错了,我将感激Java 8专家对此的任何见解。

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