Która metoda łańcuchowa: "contains" lub "indexOf> -1"?

Który z poniższych sposobów jest skutecznym sposobem określania ograniczenia podciągu?

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

Lub

if (str.contains("/")) 
Author: Alex Lockwood, 2012-05-23

8 answers

Spójrz na java.lang.String Kod źródłowy. Metoda contains jest zaimplementowana przy użyciu wywołania indexOf, więc są one zasadniczo takie same.

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

Powinieneś użyć dowolnej metody, która sprawi, że Twój kod będzie bardziej czytelny. Jeśli sprawdzasz, czy łańcuch zawiera określony podłańcuch, użyj contains. Jeśli szukasz indeksu początkowego podłańcucha, użyj indexOf.


Edit:

Kilka odpowiedzi mówi, że indexOf powinno być preferowane zamiast contains ze względu na fakt to contains powoduje dodatkowe wywołanie metody, a tym samym jest mniej efektywne. To jest złe. nagłówek wywołany dodatkowym wywołaniem metody w tym przypadku jest zupełnie nieistotny. Użyj dowolnej metody, która ma największy sens w kontekście Twojej implementacji. Dzięki temu Twój kod będzie bardziej czytelny.

 70
Author: Alex Lockwood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-26 15:10:05

Pomyślałem, że wezmę empiryczne podejście do tego pytania, zamiast zgadywać, jak narzut dodatkowego wywołania metody wpłynie na wynik. Wziąłem benchmark indexOf z tej odpowiedzi i dodałem dwie metody benchmarkowe dla contains() (jedna, która pobiera stałą ciągu, a druga, która pobiera zmienną). Używam właśnie wydanej 1.8.0_71 działającej w systemie Windows x64.

# 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

Należy zauważyć, że pomiary wzorcowe to nanosekundy na operację. Więc porównując contains("z") VS. indexOf("z"), indexOf() jest bardzo nieco szybszy, ale o mniej niż 0,6 ns. Co ciekawe, pośrednia (przy użyciu zmiennej) ma większą różnicę nieco ponad 1ns.

Umieściłem kod dla tego benchmarka na Githubie: https://github.com/tedyoung/indexof-contains-benchmark

 11
Author: Ted M. Young,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:05

Jeśli celem jest ustalenie, czy jeden ciąg zawiera inny, to contains() jest wyraźnym zwycięzcą. To sprawi, że inni programiści będą bardziej efektywni w zrozumieniu twoich intencji.

 3
Author: Peter Niederwieser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 16:09:27

W zasadzie oba są takie same,

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

Ale jeśli chcesz zrobić coś przez indeks, możesz użyć indexOf.

Wierzę, że indexOf będzie bardziej efektywny, ale różnicę można zignorować.

 3
Author: Pau Kiat Wee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-24 22:37:25

Metody mają inne zastosowanie, jeśli chcesz sprawdzić, czy łańcuch zawiera coś, użyj contains, ale jeśli chcesz wiedzieć, gdzie w łańcuchu jest to ostatecznie zawarte, użyj metody indexOf.

 2
Author: aleroot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-23 06:10:28

Podczas gdy użycie str.contains("/") jest wyraźnie bardziej czytelne, prawdopodobnie bardziej efektywne jest użycie str.indexOf('/') > -1. Zauważ, że w wywołaniu indexOf używam znaku zamiast ciągu znaków.

Ale to nie powinno mieć znaczenia pod względem wydajności, chyba że jesteś w bardzo ciasnej pętli.

 2
Author: Alexander Kjäll,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-18 10:17:50

Ostatnio miałem ten problem używając indexOf(): gdy próbowałem dowiedzieć się czy łańcuch zawiera spacje, aby zastąpić je czymś innym, odpowiedź z IndexOf brzmiała: łańcuch nie ma spacji, co było złą odpowiedzią. Po zastąpieniu przez Contains() odpowiedź była właściwa . Idź sobie, bo jak niektórzy tu powiedzieli, Contains() wysyła wezwanie do IndexOf.

 1
Author: agcala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-04 16:00:39

W przypadku wyszukiwania pojedynczego znaku, takiego jak twój przykład, indexOf jest bardziej wydajny , jeśli argument indexOf jest znakiem :

if (str.indexOf('/') > -1)
 1
Author: Paul Jackson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-15 15:35:49