2014-06-05 18 views
13

Przeglądałem nowo dodane funkcje wprowadzone w języku Java-8. Jedna prosta funkcja nowo dodana do klasy String jest dla mnie cicha i atrakcyjna - czyli String Join method.Java 8: Operacja łączenia ciągów ma znaczący wpływ na wydajność

Przykład:

String.join(" ", "AZY","BAX"); // returns AZY BAX 

Dla ciekawości sprawdziłem (czas wykonania) wykonywanie tej funkcji poprzez napisanie prostego kodu java

public static void main(String[] args) { 
    long start = System.nanoTime(); 
    String abc= String.join(" ,"AZY","BAX" … // joining 1000 words of size 3 char; 
    long diff = System.nanoTime() - start; 
    System.out.println(" Java 8 String Join " + diff); 

    start = System.nanoTime(); 
    abc= "AZY"+"BAX"+"CBA"+ … // adding 1000 word of size 3 char; 
    diff = System.nanoTime() - start; 
    System.out.println(" Tranditional " + diff); 

    start = System.nanoTime(); 
    new StringBuilder().append("AZY").append("BAX").appe… // appending 1000 word of size 3 char; 
    diff = System.nanoTime() - start; 
    System.out.println(" String Builder Append " + diff); 

} 

Wynik nie jest tak ekscytujące dla mnie (time in neno sec)

Java 8 String Join  1340114 
Tranditional    59785 
String Builder Append 102807 

Złożoność jest o (n) - w rzeczywistości jest (n * Rozmiar ind długość pojedynczego elementu)

Inne miary wydajności (pamięć itp.) Nie mierzyłem.

Moje pytania są następujące:

  1. Czy jest coś złego w moim pomiaru (przez większość czasu uważam na facetów JDK)
  2. Co jest celem dodawania „join” API do klasy String
  3. Czy jest dostępna analiza wydajności dla języka Java 8
+13

Pisanie poprawnego testu porównawczego w języku Java nie jest tak proste z powodu heurystyki JIT i zbierania śmieci. Zobacz [Jak napisać poprawny mikro-benchmark w Javie?] (Http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). – Jesper

+0

Z ciekawości, dlaczego ktoś użyłby tej metody zamiast '+ '? – Djon

+11

Również łączenie literałów łańcuchowych odbywa się podczas kompilacji, więc nie testujesz niczego w drugim teście. – Jesper

Odpowiedz

42

Po pierwsze. To nie jest sposób w jaki mikrobisz Javę

Przeczytaj najpierw How do I write a correct micro-benchmark in Java?. Twoje liczby są zupełnie nieistotne, więc zignorujmy je.

Patrząc na drugi przykład:

abc= "AZY"+"BAX"+"CBA"+... 

one wyglądać kompilacji stałych czasowych do mnie. Ten String byłby łączony w czasie kompilacji i nie byłoby niczego do porównania. Jest to bezużyteczne porównanie, ponieważ cały punkt StringBuilder lubma łączyć konkretyzacje String s, które nie są stałą czasową kompilacji.

Przeprowadzka na porównanie StringBuilder i String.join. Patrząc na kod źródłowy:

public static String join(CharSequence delimiter, CharSequence... elements) { 
    Objects.requireNonNull(delimiter); 
    Objects.requireNonNull(elements); 
    // Number of elements not likely worth Arrays.stream overhead. 
    StringJoiner joiner = new StringJoiner(delimiter); 
    for (CharSequence cs: elements) { 
     joiner.add(cs); 
    } 
    return joiner.toString(); 
} 

ta wykorzystuje StringJoiner. A StringJoiner po prostu używa pod maską StringBuilder, więc oba są równoważne.

Często o wiele bardziej interesujący jest wygląd pod kodem niż próba porównania wydajności. Nawet jeśli wykonasz benchmark poprawnie.

Warto również zauważyć, że twoja pierwsza metoda z join dołącza do 1000 String s na "" (spacja). Podczas gdy twoja metoda StringBuilder po prostu łączy je razem. Te dwa to nie to samo.

Punktem metody String.join jest to, że można zrobić:

String.join(", ", "a", "b", "c") // result is "a, b, c" 

Z StringBuilder trzeba by dodać dużo więcej kodu.

+0

To pytanie nie próbuje t o benchmark Java. ale żeby zrozumieć intencję interfejsu API "dołącz". (Myślę, że jasno wynika z pytań). Nie jestem jeszcze pewien, dlaczego potrzebujemy API, który wykonuje zagnieżdżanie w pętli (jeden w metodzie String.jave-join(), jak powiedziałeś, który wewnętrznie wywołuje metodę append() w AbstractStringBuilder) zamiast używać StringBuilder bezpośrednio – dgm

+20

@dipankaj, ponieważ cały punkt Javy 8 to dodawanie metod, które unikają jawnej pętli i używają bardziej funkcjonalnych paradygmatów. 'String.join' ma być skrótem do' Stream.of (a, b, c) .collect (Collectors.joining()) '. Jeśli nie widzisz korzyści polegających na umożliwieniu użytkownikom przyłączenia się do 'ciągu' w jednym wierszu kodu zamiast 4, to po prostu go nie używaj ... –

+0

Jeśli nie jest to udokumentowane, oczekiwane zachowanie, będzie to zależne od JVM. Z której JVM tego wyciągnąłeś? W pewnym momencie spodziewałem się, że zsumuje długość łańcuchów w tablicy i po prostu utworzy docelową tablicę. Zwłaszcza, że ​​używanie takiego budowniczego prawdopodobnie przypisze tablice wiele razy, jeśli masz do czynienia z liczbą łańcuchów, z którymi OP ma do czynienia ... –

Powiązane problemy