Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    Espressione Java8 - da che lato iniziare a leggere?

    Ciao a tutti,
    ogni tanto programmicchio, ho incontrato un programma scritto in Java 8 e ci sono cose che non capisco. Premesso che ho letto varie cose e più o meno ho presente vari concetti nuovi come le lambda (io imparai il JAva 2...), non riesco a decifrare 2 righe dello spezzone che riporto in seguito.
    Si tratta di una sfilza di chiamate a cascata che includono il nuovo operatore ::, mi potreste dire cosa ci capite?
    Più che altro vorrei una dritta da che lato cominciare a leggere, sfruttando questo esempio per capire grosso modo che cosa fa.
    In modo che la prossima volta che incontro una cosa del genere possa capirla da solo.


    codice:
    classe X... {
      private List<TipiDiAutorizzazione> autorizzazioni;
    
      //....
      public JsonObject creaERestituisciJson() {
          JsonArrayBuilder arrayAutorizzazioni = Json.createArrayBuilder();
        //delle 2 righe seguenti, ci capite qualcosa? Quale è il segreto per decifrare robe come questa??
                 autorizzazioni.AUTORIZZAZIONI_ATTIVE.stream().filter(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::containsKey)
                  .map(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::get).forEach(permissionsArray::add);
          return new JObjectBuilder().add("aut", arrayAutorizzazioni).build();
      }
    }
    Grazie
    Ultima modifica di cofra347; 16-11-2017 a 21:46
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    Si tratta di una sfilza di chiamate a cascata che includono il nuovo operatore ::, mi potreste dire cosa ci capite?
    Sono "novità" introdotte in Java 8, che ha portato nel linguaggio parecchie nuove cose tra cui principalmente: lambda expression e i method reference (insieme al concetto di functional interface). Inoltre Java 8 ha introdotto nel framework la Stream API.
    Tutto questo principalmente per portare la programmazione in Java più verso la programmazione funzionale.

    Credo sia ovvio che non si può spiegare tutto questo in un post sul forum ...

    Prima di arrivare a capire tutta quella parte, dovresti partire con l'apprendere cosa è una lambda expression in Java.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  3. #3
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Credo sia ovvio che non si può spiegare tutto questo in un post sul forum ...
    Ciao, "ovvissimo", ma non volevo questo.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    Prima di arrivare a capire tutta quella parte, dovresti partire con l'apprendere cosa è una lambda expression in Java.
    Forse mi sono spiegato male; ho modificato il messaggio proprio per scrivere che so cosa è una funzione lambda (in precedenza ho solo scritto che ho letto su tutte le novità). Siccome ho un'infarinatura di tutto ciò che c'è di nuovo, vorrei la spiegazione di quella espressione in particolare che nonostante tutto, non capisco.

    Per esempio, mi pare quasi di arrivarci, ecco una mia "traduzione", dove non capisco cosa sia la X

    « filtra, dallo stream di AUTORIZZAZIONI_ATTIVE quelle che contengono la chiave X , e crea una mappa; per ogni elemento di tale mappa aggiungilo ad autorizzazioni »

    Ammesso che sia giusto... manca qualcosa: da dove prende la chiave che ho indicato con X?
    Rriscrivo l'espressione, per non dover riguardare sopra (dove contiene un errore: permissionArray dovrebbe essere arrayAutorizzazioni, ma ormai non posso correggere per esaurimento del tempo in cui si può fare)

    codice:
    autorizzazioni.AUTORIZZAZIONI_ATTIVE.stream().filter(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::containsKey)
                  .map(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::get).forEach(arrayAutorizzazioni::add);
    Ultima modifica di cofra347; 16-11-2017 a 23:11
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    .filter(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::cont ainsKey)
    containsKey (è di una Map) restituisce un boolean, che serve al filter. Quindi filter passa ciascun oggetto al containsKey di quella mappa e ne riceve un boolean. Se è true, filter "accetta" l'oggetto e lo fa passare più avanti.

    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    .map(Autorizzazioni.AUTORIZZAZIONI_ATTIVE::get)
    map, nonostante il nome, NON ha a che fare con le mappe. L'operazione di "map" trasforma un valore in un altro. Quindi map passa al get di quella mappa l'oggetto (che funge da chiave) e ne ottiene il valore.

    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    .forEach(arrayAutorizzazioni::add);
    Questo è il più facile. Per ciascun oggetto ottenuto a questo punto, lo passa al add di arrayAutorizzazioni.


    Non ho una visione completa del tuo codice ma il senso dedotto è questo.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  5. #5
    Grazie, sì AUTORIZZAZIONI_ATTIVE è una Map.

    Ora va un poco meglio ma non riesco ancora a capire come diamine fa containsKey() a restituire qualcosa se non gli passo niente. O meglio non vedo dove riceve la chiave da valutare per restituire vero o falso a seconda che la trovi nella mappa (la X del mio precedente commento).

    Forse salto questo pezzo e vado avanti per capire il resto.
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    ma non riesco ancora a capire come diamine fa containsKey() a restituire qualcosa se non gli passo niente.
    Certo che gli viene passato qualcosa. L'espressione Autorizzazioni.AUTORIZZAZIONI_ATTIVE::containsKey NON è la invocazione di containsKey. E' invece una sorta di riferimento al containsKey di quella mappa, che viene passato al filter.
    Il filter riceve una "funzione" (nel senso delle functional interface di Java 8) che riceve un oggetto e restituisce un boolean. E il "corpo" di questa funzione è appunto la invocazione di containsKey.

    E' equivalente ad una lambda:

    codice:
    .filter(elem -> Autorizzazioni.AUTORIZZAZIONI_ATTIVE.containsKey(elem))

    Qui l'espressione della lambda sta effettivamene invocando il containsKey.
    Ultima modifica di andbin; 17-11-2017 a 00:01
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  7. #7
    Eureka, sono un idiota.
    autorizzazioni è inizializzato nel costruttore , e contiene appunto quelle chiavi che poi sono passate a containsKey per la ricerca e restituzione vero/falso.

    Devo ancora ripensarci (usando anche le tue indicazioni) ma almeno ora ho tutti gli elementi per farlo.

    Per oggi sono distrutto, se questa è stata la vigilia di domani venerdì 17 allora domani forse non mi alzo proprio dal letto.

    Dankon, ankoraŭfoje.
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

  8. #8
    Un poco fuori tema, credo che il programmatore abbia voluto strafare, infatti più semplicemente, leggibilmente e efficientemente si sarebbe potuto usare il seguente algoritmo, in pseudocodice:

    codice:
    per ogni elemento "chiave" in autorizzazioni {
      arrayAutorizzazioni.add(Autorizzazioni.AUTORIZZAZIONI_ATTIVE[chiave] ) //prendi e aggiungi l'elemento con quella chiave
    }
    Forse questo funziona ma devo provarlo:

    codice:
    for (TipoAutorizzazione chiave: autorizzazioni) {
        arrayAutorizzazioni.add(Autorizzazioni.AUTORIZZAZIONI_ATTIVE.get(chiave));
    }
    Invece si serializza l'array delle chiavi, si creano filtri e un sacco di casini (senza aggiungere uno straccio di commento).

    Roba da matti, ma il mio scopo alla fine è comprenderlo come esempio didattico.
    Ultima modifica di cofra347; 17-11-2017 a 10:05
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

  9. #9
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,254
    Quote Originariamente inviata da cofra347 Visualizza il messaggio
    credo che il programmatore abbia voluto strafare
    Non è questione di "strafare". Con lambda expression/method reference e la Stream API è possibile scrivere codice più compatto, PIÙ leggibile e nell'ottica di una programmazione più "funzionale".

    Se hai un array di nomi:

    codice:
    String[] nomiColleghi = {
            "Andrea", "Cecilia", "Claudio", "Damiano", "Davide",
            "Emanuele", "Enrico", "Giorgio", "Giuseppe", "Liliana",
            "Luigi", "Maurizio", "Michele", "Paolo", "Sara", "Serena",
            "Simona", "Simone"
    };

    E vuoi ottenere un List con i nomi lunghi al massimo 6 caratteri e portati tutti in maiuscolo, puoi fare normalmente:

    codice:
    List<String> res = new ArrayList<String>();
    
    for (String nome : nomiColleghi) {
        if (nome.length() <= 6) {
            res.add(nome.toUpperCase());
        }
    }

    Oppure con Stream API+lambda expression:

    codice:
    List<String> res = Arrays.stream(nomiColleghi)
            .filter(nome -> nome.length() <= 6)
            .map(String::toUpperCase)
            .collect(Collectors.toList());

    La vedi la differenza? Quest'ultimo è più compatto e leggibile. Qui c'è solo un "filtro" e un "mapping", che effettivamente sono banali, ma immagina ci siano operazioni anche di grouping e altro.

    Se il codice lo scrivi tu "a mano" con cicli, if, ecc.. il codice diventa lungo, prolisso, quasi sicuramente poco leggibile e anche dispersivo. E oltretutto NON (facilmente) parallelizzabile.

    Invece se avessi un array con 20000 nomi, puoi usare un parallel stream mettendo semplicemente:

    Arrays.stream(nomiColleghi).parallel().blabla

    Dato che la sorgente dei dati è un array, la parallelizzazione è molto efficace. E ti permette di sfruttare i core del processore. Se invece scrivi tu for, if, il tuo codice non è di per sé parallelizzabile. Per renderlo parallelizzabile, bisogna avere nozioni abbastanza elevate sul multi-threading/concorrenza. E dovresti ripetere la cosa o in più posti (non buono) o farti una piccola architettura che sarebbe sostanzialmente similare a quella della Stream API.

    Più chiaro, ora?
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    Java Versions Cheat Sheet

  10. #10
    Capisco i motivi della parallelizzazione, per la leggibilità umana, forse ci si arriva con l'abitudine, a prima vista mi pare più leggibile il for scritto a mano.
    Il tuo esempio mi sembra invece chiaro anche con la nuova sintassi, al contrario di quello che ho incontrato io.

    Però, forse, abituàndocisi e vedendo sempre questa sintassi... vedremo col tempo, devo ancora digerire queste novità.
    Ultima modifica di cofra347; 17-11-2017 a 11:22
    Libero > imposto
    Lunux > Windows
    Esperanto > lingua del padrone
    Kirek
    (dove > è "maggiore di")

Tag per questa discussione

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 © 2024 vBulletin Solutions, Inc. All rights reserved.