2015-07-08 5 views
6

Voglio creare una stringa delle coppie di valori chiave della mia HashMap<String, String> m il più velocemente possibile.Come convertire un HashMap ad un K/V-String in Java 8 con Streams

ho provato:

StringBuffer buf = new StringBuffer(); 
buf.append("["); 
for (String key : m.keySet()) { 
    buf.append(key); 
    buf.append("="); 
    buf.append(m.get(key)); 
    buf.append(";"); 
} 
buf.append("]"); 

Con Java8 ho provato:

m.entrySet().stream() 
      .map(entry -> entry.getKey() + " = " + entry.getValue()) 
      .collect(Collectors.joining("; " , "[" , "]")); 

Esiste un codice più veloce di meglio da fare che? Sembra essere costoso aggiungere le chiavi e i valori nella funzione mappa, vero?

+3

Quando si profilata entrambi questi approcci, che correva più veloce rispetto agli altri? E quanto più veloce? –

+4

In questo caso non mi preoccuperei delle prestazioni ** a meno che ** non sia una parte critica del sistema e viene indicato come collo di bottiglia dall'utilizzo di un profiler o di uno strumento simile. Se non lo hai fatto prima e pensi * questo codice non è ottimale, allora I̶ ̶k̶n̶o̶w̶ ̶t̶h̶a̶t̶ forse hai torto e dovresti testarlo prima. –

+0

FWIW - Il risultato di 'm.toString()' potrebbe essere abbastanza vicino per te non importa. –

risposta

8
map -> map.entrySet().stream().map(Entry::toString).collect(joining(";", "[", "]")) 

(Si noti che ho omesso le importazioni.)

Come Luiggi Mendoza detto:

io non mi preoccuperei di prestazioni in questo caso a meno che non si tratta di una parte fondamentale del sistema e viene indicato come collo di bottiglia dall'utilizzo di un profiler o di uno strumento simile. Se non lo hai fatto prima e pensi che questo codice non sia ottimale, allora I̶ ̶k̶n̶o̶w̶ ̶t̶h̶a̶t̶ forse hai torto e dovresti testarlo prima.

+3

La chiamata 'Collectors.joining()' dell'OP aveva il delimitatore, prefisso, suffisso errato. La tua soluzione l'ha risolto. –

+3

Si noti che mentre 'Entry.toString()' di solito restituisce 'chiave = valore', non è esplicitamente richiesto dalla [Voce] (http://docs.oracle.com/javase/7/docs/api/java/util /Map.Entry.html), quindi potresti lanciare l'implementazione della mappa che restituisce qualcos'altro. Preferirei una concatenazione esplicita come nella domanda. –

+0

Ho esaminato l'interfaccia 'Entry'. Non ho potuto correggere nessuna dichiarazione 'toString'. Potresti spiegare come 'Entry :: toString()' definisce? Un'altra cosa, solo 'Entry :: toString' non può risolvere nella mia fine. Devo fare 'Map.Entry :: toString()'. – seal

0

Utilizzare StringBuilder anziché buffer.

Javadoc => Classe StringBuffer

"La classe StringBuilder deve essere usata in preferenza a questo, in quanto supporta tutte le stesse operazioni, ma è più veloce, come si esegue alcuna sincronizzazione." Class StringBuffer

+2

La domanda dell'OP riguarda il secondo pezzo di codice. –

+0

è più veloce della soluzione con lo stream? Potrebbero essere combinati entrambi? – Joel

+0

Mentre usare StringBuilder potrebbe essere più veloce di StringBuffer per il primo pezzo di codice, la domanda riguarda specificamente la velocità del secondo pezzo di codice, come sottolinea @LuiggiMendoza. – Vulcan

-1
@Test 
public void testMapPrint() { 
    Map<String, String> map = new HashMap<>(); 
    map.put("a", "b"); 
    map.put("c", "d"); 

    map.entrySet().stream() 
      .forEach(entry -> System.out.println(entry.getKey() + ":" + entry.getValue())); 
} 
+0

La stampa di ciascuna coppia sulla console richiede molto tempo. Raccogliere tutto in una stringa {Builder, Builder} e quindi stamparlo è molto probabilmente più veloce. –

+0

Bene, se vuoi entrare nel microbenchmarking dovresti considerare anche la situazione in cui il char array nel generatore di stringhe si sta estendendo (è anche costoso, per impostazione predefinita viene creato char [16]) :) – rgrebski

+0

Se vuoi stampare direttamente una mappa, lì non è necessario un 'Stream'. Basta usare 'map.forOach ((k, v) -> System.out.println (k +": "+ v));' – Holger