2014-07-23 13 views
10

voglio essere in grado di convertire un List ad un HashMap in cui la chiave è la elementName ei valori è un elenco di qualcosa di casuale (in questo caso il suo nome dell'elemento). Quindi insomma voglio (A->List(A), B->List(B), C-> List(C)). Ho provato a utilizzare toMap() e passandolo a keyMapper e ValueMapper ma ottengo un errore di compilazione. Apprezzerei molto se qualcuno potesse aiutarmi.raccolta HashMap <String, Lista <String>> java 8

Grazie!

public static void main(String[] args) { 
    // TODO Auto-generated method stub 
    List<String> list = Arrays.asList("A","B","C","D"); 
    Map<String, List<String>> map = list.stream().map((element)->{ 
     Map<String, List<String>> map = new HashMap<>(); 
     map.put(element, Arrays.asList(element)); 
     return map; 
    }).collect(??); 
} 


Function<Map<String, String>, String> key = (map) -> { 
    return map.keySet().stream().findFirst().get(); 
}; 

Function<Map<String, String>, String> value = (map) -> { 
    return map.values().stream().findFirst().get(); 
}; 

=== Questo ha funzionato per me

Grazie per tutto l'aiuto ragazzi! @izstas "dovrebbero operare sugli elementi" ha aiutato molto :). In realtà questo è quello che cercavo per l'esattezza

public static void test2(){ 
    Function<Entry<String, List<String>>, String> key = (entry) -> { 
     return entry.getKey(); 
    }; 
    Function<Entry<String, List<String>>, List<String>> value = (entry) -> { 
     return new ArrayList<String>(entry.getValue()); 
    }; 
    BinaryOperator<List<String>> merge = (old, latest)->{ 
     old.addAll(latest); 
     return old; 
    }; 

    Map<String, List<String>> map1 = new HashMap<>(); 
    map1.put("A", Arrays.asList("A1", "A2")); 
    map1.put("B", Arrays.asList("B1")); 
    map1.put("D", Arrays.asList("D1")); 

    Map<String, List<String>> map2 = new HashMap<>(); 
    map2.put("C", Arrays.asList("C1","C2")); 
    map2.put("D", Arrays.asList("D2")); 

    Stream<Map<String, List<String>>> stream =Stream.of(map1, map2); 
    System.out.println(stream.flatMap((map)->{ 
     return map.entrySet().stream(); 
    }).collect(Collectors.toMap(key, value, merge))); 
} 
+2

Qual è l'errore del compilatore? –

+0

Pubblica il tuo codice sorgente, vedi [Come creare un esempio minimale, completo e verificabile] (http://stackoverflow.com/help/mcve) – DavidPostill

+0

Non sono sicuro, ma per quanto ne so nella tua mappa parte qualsiasi cosa tu dal lato sinistro deve corrispondere con il lato destro, quindi dovresti restituire elemento non mappa penso :) –

risposta

15

Funzioni key e value aver definito nel codice non sono corretti perché dovrebbe operare sui elementi della tua lista, e gli elementi non sono Map S.

Il seguente codice funziona per me:

List<String> list = Arrays.asList("A", "B", "C", "D"); 
Map<String, List<String>> map = list.stream() 
     .collect(Collectors.toMap(Function.identity(), Arrays::asList)); 

primo argomento di Collectors.toMap definisce come fare una chiave dall'elemento lista (lasciando così com'è), secondo argomento definisce come rendere un valore (facendo un ArrayList con un singolo elemento).

+1

Hai preso in considerazione la sostituzione (elemento) -> elemento con Funzione. identity()? – Jeff

+0

@Jeff Oh, questo è un bel suggerimento. Aggiornerò la mia risposta A proposito, sembra funzionare per me senza dover specificare esplicitamente il parametro type. – izstas

+0

Freddo. Sì, il tipo non è necessario. Era una copia/incolla. – Jeff

5

Grazie per tutto l'aiuto ragazzi! @izstas "dovrebbero operare sugli elementi" ha aiutato molto :). In realtà questo è quello che cercavo per l'esattezza

public static void test2(){ 
    Function<Entry<String, List<String>>, String> key = (entry) -> { 
     return entry.getKey(); 
    }; 
    Function<Entry<String, List<String>>, List<String>> value = (entry) -> { 
     return new ArrayList<String>(entry.getValue()); 
    }; 
    BinaryOperator<List<String>> merge = (old, latest)->{ 
     old.addAll(latest); 
     return old; 
    }; 

    Map<String, List<String>> map1 = new HashMap<>(); 
    map1.put("A", Arrays.asList("A1", "A2")); 
    map1.put("B", Arrays.asList("B1")); 
    map1.put("D", Arrays.asList("D1")); 

    Map<String, List<String>> map2 = new HashMap<>(); 
    map2.put("C", Arrays.asList("C1","C2")); 
    map2.put("D", Arrays.asList("D2")); 

    Stream<Map<String, List<String>>> stream =Stream.of(map1, map2); 
    System.out.println(stream.flatMap((map)->{ 
     return map.entrySet().stream(); 
    }).collect(Collectors.toMap(key, value, merge))); 
} 
17

È possibile utilizzare il metodo groupingBy per gestire l'aggregazione, ad esempio:

public static void main(String[] args) { 
    List<String> list = Arrays.asList("A", "B", "C", "D", "A"); 
    Map<String, List<String>> map = list.stream().collect(groupingBy(Function.identity())); 
} 

Se si desidera una maggiore flessibilità (ad esempio per mappare il valore e restituire un set al posto di una lista) si può sempre utilizzare il metodo groupingBy con più parametri come specificato nel javadoc:

Map<City, Set<String>> namesByCity = people.stream().collect(groupingBy(Person::getCity, mapping(Person::getLastName, toSet()))); 
+0

groupingBy esiste? –

+1

Ho corretto l'esempio mi dispiace. Il metodo 'groupingBy' è un metodo statico in' java.util.stream.Collectors'. – Phoenix

+0

Grazie! Mi ha aiutato a – zhuguowei