2014-06-05 10 views
13

Stavo passando per le nuove funzionalità esistenti introdotte in Java-8. Una semplice funzionalità appena aggiunta alla classe String è tranquillamente interessante per me, ovvero String Join method.Java 8: l'operazione di join delle stringhe ha un impatto significativo sulle prestazioni

Esempio:

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

Per curiosità, ho controllato le prestazioni (tempo di esecuzione) di questa funzione scrivendo un codice java semplice

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); 

} 

Il risultato non è così eccitante per me (ora in neno sec)

Java 8 String Join  1340114 
Tranditional    59785 
String Builder Append 102807 

La complessità è di o (n) - in effetti è (n * Dimensione dell'ind lunghezza elemento singolo)

Altre misure di prestazione (memoria ecc.) Non ho misurato.

Le mie domande sono:

  1. qualcosa che non va nella mia misura (il più delle volte credo sui ragazzi JDK)
  2. Qual è l'intento di aggiungere “join” API per classe String
  3. È disponibile un'analisi delle prestazioni per Java 8
+13

Scrivere un benchmark corretto in Java non è così semplice a causa dell'euristica e della garbage collection JIT. Vedi [Come posso scrivere un micro-benchmark corretto in Java?] (Http://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java). – Jesper

+0

Per curiosità, perché si dovrebbe usare questo metodo invece di '+'? – Djon

+11

Inoltre, la concatenazione di stringhe letterali viene eseguita in fase di compilazione, quindi non si sta verificando nulla nel secondo test. – Jesper

risposta

42

Per prima cosa. Questo non è il modo in cui microbench Java

Leggere prima How do I write a correct micro-benchmark in Java?. I tuoi numeri sono completamente irrilevanti, quindi lasciali ignorare.

Guardando il secondo esempio:

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

Questi sembrano costanti di tempo di compilazione per me. Questo String verrebbe concatenato in fase di compilazione e non ci sarebbe nulla da confrontare. Si tratta di un confronto inutile poiché l'intero punto di StringBuilder o String.join consiste nel concatenare String s che non sono costanti di tempo di compilazione.

Passare al confronto tra StringBuilder e String.join. Guardando il codice sorgente:

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(); 
} 

Questo utilizza un StringJoiner. Un StringJoiner utilizza semplicemente un StringBuilder sotto il cofano, quindi i due sono equivalenti.

Spesso è molto più informativo guardare al codice piuttosto che provare e confrontare le prestazioni. Anche se fai benchmark correttamente.

Vale anche la pena notare che il tuo primo metodo, con join, si aggiunge a 1000 String s su "" (spazio). Mentre il tuo metodo StringBuilder li aggiunge semplicemente insieme. Questi due non sono gli stessi.

Il punto del metodo String.join è che si può fare:

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

Con un StringBuilder si dovrà aggiungere un codice molto di più.

+0

Questa domanda non sta provando t o benchmark Java. ma per capire l'intento dell'API "join". (Penso che sia chiaro dalle domande). Non sono ancora sicuro del motivo per cui abbiamo bisogno di un'API che nidifica in loop (uno nel metodo String.jave-join() come hai detto che invoca internamente il metodo append() di AbstractStringBuilder) invece di usare StringBuilder direttamente – dgm

+20

@dipankaj perché l'intero punto di Java 8 consiste nell'aggiungere metodi che evitano il looping esplicito e utilizzano paradigmi più funzionali. 'String.join' dovrebbe essere una scorciatoia per' Stream.of (a, b, c) .collect (Collectors.joining()) '. Se non si vedono i vantaggi di consentire agli utenti di unirsi a un 'String' in una riga di codice anziché in 4, non utilizzarlo semplicemente ... –

+0

A meno che non sia documentato, comportamento previsto, questo dipenderebbe da JVM. Da quale JVM hai tratto questo? In qualche modo mi aspettavo che sommasse la lunghezza delle stringhe nell'array e creasse semplicemente l'array di destinazione. Soprattutto perché usare un costruttore del genere è probabile che allocare array più volte se si ha a che fare con il numero di stringhe che l'OP ha a che fare con ... –

Problemi correlati