2015-06-19 7 views
24

In C# gibt es eine Möglichkeit, die Länge einer If-Anweisung zu reduzieren, indem Enumerable.Any verwendet, um zu überprüfen, ob Elemente in einer Sequenz eine Bedingung erfüllen (https://msdn.microsoft.com/en-us/library/vstudio/bb534972%28v=vs.100%29.aspx).Java-Äquivalent von C# 'Enumerable.Any'

Zum Beispiel Statt:

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

Wir verwenden

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

Gibt es ein Äquivalent, wenn nicht besser, diese Art und Weise in Java zu tun?

+1

Nur der Vollständigkeit halber: Sie können auch '.Any (string.Contains)' anstelle der ausführlicher '.Any (w => string.Contains (w))' in C# verwenden. – Bob

Antwort

23

Mit Java 8 können Sie so etwas wie schreiben:

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

Aus Neugier lief ich eine Benchmark diese Methode vs Regex zu vergleichen. Code und Ergebnisse unten (niedrigerer Wert = schneller). Streams sind um eine Größenordnung besser als 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).*$"); 
    } 
} 
+0

@MarcoAcierno String :: contains verweisen auf eine statische Methode, die nicht existiert. https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html – Ezequiel

+2

Mein schlechtes, entfernte ich den Kommentar. Ich vermisste die Tatsache, dass "String" eine Variable ist –

+0

Danke für die Klärung. Ich frage mich, ob Regex schneller für die Überprüfung von Teilstrings statt einzelner Zeichen wäre. Ich bin mir nicht sicher, ob 'contains()' in diesen Fällen gut funktioniert. –

9

Mit Java 8, das ist möglich mit dem anyMatch Methode:

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

} 
6

Wenn Sie Java nicht über 8, können Sie nur einen normalen Gebrauch Ausdruck, um Ihre Aufgabe zu erfüllen.

string.matches("^.*?(<|>|p|1|&).*$") sollte den Trick tun.

EDIT:

Ich frage mich, welche Lösung schneller ausführt. Obwohl JIT alle Lambda-Goodiness inline einbinden kann, sind Stream (s) möglicherweise langsamer als ein regulärer Ausdruck. Ich könnte völlig falsch liegen und ich würde jede Einsicht von Java 8 Stalwarts schätzen.

+0

Danke! Das funktioniert perfekt. – Mirodinho

+1

@ Amrito10, jederzeit! –