2016-04-11 17 views
14

Quindi supponiamo di avere un oggetto . Quella classe dell'oggetto è come questo:Contare le proprietà degli oggetti nell'elenco utilizzando java 8

class Animal{ 
    String Name;//for example "Dog" 
    String Color 
} 

Quello che voglio fare è contare quante esistono diversi colori per ogni animale in ArrayList e metterli in un Map<String,Integer> dove String è il nome e Integer è per il numero di colori diversi.

Per esempio, se ci sono 4 cani neri e 1 bianco della put equivalente alla mappa sarebbe

map.put("Dog",2); 

so che può essere fatto utilizzando Stream ma non riesco a trovare il modo.

risposta

19

Quello che vuoi fare è un grouping operation utilizzando la proprietà name come chiave. Questa è la parte facile. Trickier è di esprimere il "conteggio di colori distinti" come collettore a valle. Poiché non esiste un collector di questo tipo in JRE, dobbiamo crearne uno, utilizzando uno spazio di archiviazione Set. Si noti che anche se ce n'era uno integrato, doveva usare un deposito simile sotto il cofano. Così abbiamo map the elements a colori, collect them into Sets (che implica mantenendo valori distinti solo) e finish interrogando il formato:

Map<String, Integer> map = animalStream.collect(
    Collectors.groupingBy(Animal::getName, 
     Collectors.collectingAndThen(
      Collectors.mapping(Animal::getColor, Collectors.toSet()), 
      Set::size))); 
5

questo dovrebbe funzionare:

Map<String, Integer> map = animal.stream().collect(
      Collectors.groupingBy(
        Animal::getName, 
        Collectors.collectingAndThen(
          Collectors.mapping(Animal::getColor, Collectors.toSet()), 
          Set::size) 
        ) 
      ); 

Ecco alcuni test-code:

public static void main(String[] args) { 
    List<Animal> animal = new ArrayList<>(); 
    animal.add(new Animal("Dog","black")); 
    animal.add(new Animal("Dog","black")); 
    animal.add(new Animal("Dog","blue")); 
    animal.add(new Animal("Cat","blue")); 
    animal.add(new Animal("Cat","white")); 

    Map<String, Integer> map = animal.stream().collect(
      Collectors.groupingBy(
        Animal::getName, 
        Collectors.collectingAndThen(
          Collectors.mapping(Animal::getColor, Collectors.toSet()), 
          Set::size) 
        ) 
      ); 

    for(Entry<String, Integer> entry:map.entrySet()) { 
     System.out.println(entry.getKey()+ " : "+entry.getValue()); 
    } 

} 

Cat : 2 
Dog : 2 

Nota: questa risposta è stato ispirato da questo SO posta: https://stackoverflow.com/a/30282943/1138523

+0

Si potrebbe, se si desidera, utilizzare Map :: forEach per il codice di prova: map.forEach ((key, value) -> System.out. println (tasto + ":" + valore)); – srborlongan

+2

Grazie, non lo sapevo –

Problemi correlati