Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 20 su 20

Hybrid View

  1. #1
    intanto ho modificato il count per impostare il limit (e levare quel count):
    codice:
     public Map<String, Long> countByAuthor(List<Book> booksList) { 
            Map<String, Long> map = booksList.stream() 
                    .limit(10) 
                    .collect(Collectors.groupingBy(Book::getAuthor, Collectors.counting())); 
            return map; 
        }

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    per impostare il limit
    Occhio che il limit è applicato sulla lista in ingresso, PRIMA di applicare il groupingBy. Quindi se la lista in ingresso non ha un qualche ordine preciso, sostanzialmente vai a raggruppare in modo parziale e un po' a caso.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Occhio che il limit è applicato sulla lista in ingresso, PRIMA di applicare il groupingBy. Quindi se la lista in ingresso non ha un qualche ordine preciso, sostanzialmente vai a raggruppare in modo parziale e un po' a caso.
    uhm ok.
    allora devo applicarlo dopo come ho fatto prima suppongo.
    perchè la lista in ingresso non devo ordinarla.
    io la map vorrei ordinarla per il count.
    in sostanza:
    codice:
    stephen king, 10
    clive cussler, 4
    thomas mann, 3
    sarebbe possibile?
    perchè non riesco ad applicare il sort sullo stream.

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    io la map vorrei ordinarla per il count.
    sarebbe possibile?
    perchè non riesco ad applicare il sort sullo stream.
    Innanzitutto non puoi farlo solo con una mappa autore -> conteggio. Le mappe NON si ordinano per valore.
    Però da questa mappa ne puoi derivare un'altra in cui hai

    conteggio --> lista autori

    "lista autori" perché più autori possono avere lo stesso conteggio! Ma ora il conteggio è come "chiave", quindi se usassi es. TreeMap per questa seconda mappa, hai un ordine (scegli tu se ascendente o discendente) sul conteggio.
    A quel punto puoi prendere gli ultimi (o i primi) N conteggi.

    Si fa, serve solo qualche passo in più con gli stream.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    ok la teoria, ma a livello pratico mi manca qualcosa:
    codice:
        public Map<String, Long> countByAuthor(List<Book> booksList) { 
            Map<String, Long> map = booksList.stream().collect(Collectors.groupingBy(Book::getAuthor, Collectors.counting())); 
            Map<String, Long> sorted = sortByValues(map); 
            return sorted; 
        } 
     
        public <K, V extends Comparable<V>> Map<K, V> sortByValues(Map<K, V> map) { 
            Comparator<K> valueComparator = (k1, k2) -> { 
                int compare = map.get(k2).compareTo(map.get(k1)); 
                return (compare == 0) ? 1 : compare; 
            }; 
            Map<K, V> sortedByValues = new TreeMap<>(valueComparator); 
            sortedByValues.putAll(map); 
            System.out.println(map); 
            System.out.println(sortedByValues); 
            return sortedByValues; 
        }
    stampando le due Map, vedo che me le ordina correttamente.
    ora però dovrei usare limit(10) sulla Map sorted, giusto?

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    codice:
        public <K, V extends Comparable<V>> Map<K, V> sortByValues(Map<K, V> map) { 
            Comparator<K> valueComparator = (k1, k2) -> { 
                int compare = map.get(k2).compareTo(map.get(k1)); 
                return (compare == 0) ? 1 : compare; 
            }; 
            Map<K, V> sortedByValues = new TreeMap<>(valueComparator); 
            sortedByValues.putAll(map); 
            System.out.println(map); 
            System.out.println(sortedByValues); 
            return sortedByValues; 
        }
    Non è molto bello ..... dico il fatto innanzitutto di accedere alla map (il parametro) che è fuori dalla lambda (quindi come effetto "collaterale") ed anche il fatto che il Comparator (che in realtà è sulle chiavi!!) vada a fare il truschino di confrontare i valori.


    Si può fare con gli stream. Guarda questo esempio:

    codice:
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    import java.util.stream.Collectors;
    
    public class Prova {
        public static void main(String[] args) {
            List<Persona> persone = Arrays.asList(
                    new Persona("Andrea"), new Persona("Mario"),
                    new Persona("Laura"), new Persona("Andrea"),
                    new Persona("Paola"), new Persona("Mario"),
                    new Persona("Andrea"));
    
            Map<String,Long> mapNomeConteggio = persone.stream()
                    .collect(Collectors.groupingBy(Persona::getNome, Collectors.counting()));
    
            System.out.println(mapNomeConteggio);
    
            Map<Long,List<String>> mapConteggioNomi = mapNomeConteggio.entrySet().stream()
                    .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new,
                            Collectors.mapping(Map.Entry::getKey, Collectors.toList())));
    
            System.out.println(mapConteggioNomi);
        }
    }
    
    class Persona {
        private final String nome;
    
        public Persona(String nome) {
            this.nome = nome;
        }
    
        public String getNome() {
            return nome;
        }
    }

    Nota che il 2° parametro del groupingBy è un Supplier<M> mapFactory che serve per fornire la map, che sopra è un TreeMap.

    Osserva l'output dei due println.
    Ultima modifica di andbin; 23-06-2017 a 16:08
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    ciao andbin!

    c'è qualcosa che mi sfugge:
    codice:
            Map<String, Long> map = booksList.stream().collect(Collectors.groupingBy(Book::getAuthor, Collectors.counting())); 
            Map<Long, List<String>> sorted = map 
                    .entrySet() 
                    .stream() 
                    .collect(Collectors.groupingBy(Map.Entry::getValue, TreeMap::new, Collectors.mapping(Map.Entry::getKey, Collectors.toList()))); 
     
            System.out.println(map); 
            System.out.println(sorted);
    il secondo output ritorna il numero di libri e poi una lista per tutti gli autori che hanno scritto quel numero di libri, corretto?
    però non tiene conto ad esempio del fatto che sul db alcuni autori sono salvati insieme.
    se 5 autori hanno scritto insieme un libro, quegli autori sono messi insieme come se fosse unico,
    quindi io potrei avere (ad esempio):
    codice:
    clive cussler = 5
    stephen king = 10
    stephne king, clive cussler = 1
    cioè:
    - ho 5 libri di clive cussler
    - ho 10 libri di stephen king
    - ho un libro scritto insieme

    invece l'output non tiene conto di questo se non erro (e soprattutto, se sono riuscito a spiegarmi!!).

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    però non tiene conto ad esempio del fatto che sul db alcuni autori sono salvati insieme.
    se 5 autori hanno scritto insieme un libro, quegli autori sono messi insieme come se fosse unico,
    Nel JSON iniziale si vede effettivamente un author del tipo:

    "author": "joseph muniz, aamir lakhani",

    Le logiche con gli Stream che abbiamo fatto finora prendono l'author per intero come "chiave" di raggruppamento. Quindi è OVVIO che "joseph muniz, aamir lakhani" crea un gruppo diverso da solo "joseph muniz" e da solo "aamir lakhani".

    Le cose sono due:
    - o cambi la modellazione del JSON in modo da strutturare meglio gli N possibili autori
    - o a valle (dopo il parsing JSON) fai una logica di parsing per spezzare la stringa negli N autori.

    E in sostanza in Book sarebbe quindi utile avere un getAuthors e di conseguenza bisognerà chiaramente aggiornare il modo di operare con gli stream (perché non puoi avere come "chiave" di raggruppamento una lista e meno che mai un array).

    In sostanza se hai:
    - un libro scritto da clive cussler
    - un libro scritto da stephen king
    - un libro scritto da clive cussler E stephen king

    Si vorrebbe ottenere che:
    clive cussler ha scritto 2 libri
    stephen king ha scritto 2 libri

    No?


    P.S. insomma, la "sparagnata" innanzitutto è stata quella di aver messo autore1,autore2......
    Ultima modifica di andbin; 26-06-2017 a 16:33
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    ok, mi sono spiegato male.
    a me va bene avere gli autori siano messi in quel modo.
    però, probabilmente, sono io che non ho capito bene una cosa.
    e quindi ho fatto una domanda per un'altra.

    una volta effettuato il secondo Stream, devo passare l'oggetto Map<Long, List<String>> al grafico per riempirlo:
    codice:
    map.forEach((k, v) -> series1.getData().add(new XYChart.Data<>(k, v)));
    in sostanza devo iterare sulla Map, e per ogni record devo prendere il nome dell'autore e il count.
    ma avendo come value una List<String>, devo eseguire una ulteriore iterazione suppongo.
    giusto?

  10. #10
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da fermat Visualizza il messaggio
    ma avendo come value una List<String>, devo eseguire una ulteriore iterazione suppongo.
    giusto?
    Sì, ovviamente.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.