2015-05-20 9 views
7

Ho due array di stringhe. Uno con un nome breve.Come mappare due array su una HashMap in Java?

// days short name 
String[] shortNames = {"SUN", "MON", "...", "SAT"}; 

L'altro con un nome lungo.

// days long name 
String[] longNames = {"SUNDAY", "MONDAY", "....", "SATURDAY"}; 

Entrambi con lo stesso numero di elementi. Come posso mappare il nome breve come KEY e il nome lungo come VALUE in HashMap?

HashMap<String, String> days = new HashMap<>(); 

Lo so, lo posso fare in loop. C'è un modo migliore?

+0

Penso looping è il modo migliore in questo contesto - quando la dimensione di queste due matrici sono gli stessi. – Razib

+0

Perché archiviare in array in primo luogo? –

risposta

14

Ci sono molti modi per farlo. Uno che è abbastanza facile da capire e da applicare è l'utilizzo di Java 8 flussi e collezionisti per mappare da un flusso di indici di coppie di valori chiave:

Map<String, String> days = IntStream.range(0, shortNames.length).boxed() 
    .collect(Collectors.toMap(i -> shortNames[i], i -> longNames[i])); 

Ci sono alcune terze librerie Java parti che includono una funzione di 'cerniera' a prendere due flussi e produrre una mappa da uno all'altro. Ma in realtà sono solo modi più semplici per ottenere la stessa cosa del codice sopra.

+0

e che dire di java 7 e di seguito? –

+0

@ 10sw33 Sotto Java 8 (oltre all'aggiornamento!) Avete ancora alcune opzioni. Utilizzare una libreria di terze parti o utilizzare 'Arrays.toList (shortNames) .forEach' per scorrere tutti gli elementi in una matrice e aggiungere le voci della mappa. So che questa è solo un'iterazione di un altro nome, ma anche i flussi sono così! – sprinter

+0

@sprinter Buona risposta, ma ha bisogno di una scatola() come Jens ha detto in seguito. –

1

Il accepted answer non ha funzionato per me, poiché lo IntStream non fornisce un metodo a un argomento collect.

Per beneficiare comunque del collettore toMap, è necessario innanzitutto inserire le primitive int negli oggetti Integer. Se vi piace di preservare l'ordine elemento, utilizzare la versione estesa di toMap insieme LinkedHashMap::new come indicato qui sotto:

package learning.java8; 

import static java.util.stream.Collectors.*; 
import static org.junit.Assert.*; 

import java.time.DayOfWeek; 
import java.time.format.TextStyle; 
import java.util.Arrays; 
import java.util.LinkedHashMap; 
import java.util.Locale; 
import java.util.Map; 
import java.util.stream.IntStream; 

import org.junit.Test; 

public class IntStreamLT { 

    @Test 
    public void q30339679() { 

     final String[] shortNames = getDayOfWeekNamesInEnglish(TextStyle.SHORT); 
     final String[] longNames = getDayOfWeekNamesInEnglish(TextStyle.FULL); 

     final Map<String, String> days = IntStream.range(0, shortNames.length).boxed() 
       .collect(toMap(i -> shortNames[i], i -> longNames[i])); 

     System.out.println(days); 

     final Map<String, String> sorted = IntStream.range(0, shortNames.length).boxed() 
       .collect(toMap(
         i -> shortNames[i], i -> longNames[i], 
         (i, j) -> i, LinkedHashMap::new)); 

     System.out.println(sorted); 

     assertEquals("{Mon=Monday, Tue=Tuesday, Wed=Wednesday, Thu=Thursday, " 
       + "Fri=Friday, Sat=Saturday, Sun=Sunday}", sorted.toString()); 
    } 

    private static String[] getDayOfWeekNamesInEnglish(final TextStyle style) { 

     return Arrays.stream(DayOfWeek.values()) 
       .map(day -> day.getDisplayName(style, Locale.ENGLISH)) 
       .toArray(String[]::new); 
    } 
} 

vedi anche: Why don't primitive Stream have collect(Collector)?

1

È possibile utilizzare org.apache.commons.lang3.ArrayUtils.

Ecco un esempio:

Map colorMap = ArrayUtils.toMap(new String[][] { 
    {"RED", "#FF0000"}, 
    {"GREEN", "#00FF00"}, 
    {"BLUE", "#0000FF"}});