Search code examples
javaif-statementstring-search

Java equivalent of C#'s 'Enumerable.Any'


In C# there is a way of reducing the length of an if-statement by using Enumerable.Any to check if elements in a sequence satisfy a condition (https://msdn.microsoft.com/en-us/library/vstudio/bb534972%28v=vs.100%29.aspx).

For example Instead of:

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

We can use

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

Is there an equivalent, if not better, way of doing this in Java?


Solution

  • With Java 8 you can write something like:

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

    Out of curiosity I ran a benchmark to compare this method vs a regex. Code and results below (lower score = faster). Streams perform an order of magnitude better than regex.

    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
    

    Code:

    @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).*$");
      }
    }