Visualizzazione dei risultati da 1 a 10 su 13

Hybrid View

  1. #1
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315

    interfacce funzionali package java.util.function

    Ho alcuni problemi con un esercizio dove è richiesto l'utilizzo dell'interfaccia funzionale Predicate.
    L'esercizio richiede di creare una classe "Citta" che astrae il concetto di città e che dichiara le variabili nome di tipo String e capoluogo e diMare di tipo boolean.
    Bisogna inoltre creare una classe TestCitta con un metodo main che stampa la lista di città sfruttando reference a metodi e interfaccia Pradicate.
    Questa è la mia soluzione:
    codice:
    package com.java8.mod15.dati;
    
    public class Citta {
        private String nome;
        private boolean capoluogo;
        private boolean diMare;
        
        public Citta(String nome, boolean capoluogo, boolean diMare) {
            this.nome=nome;
            this.capoluogo=capoluogo;
            this.diMare=diMare;
        }
        
        public boolean isDiMare() {
            if(diMare == true) {
                return true;
            }
            else {
                return false;
            }
        }
        
        public boolean isCapoluogo() {
            if(capoluogo == true) {
                return true;
            }
            else {
                return false;
            }
        }
        
        public String toString() {
            return nome;
        }
    }
    codice:
    package com.java8.mod15.test;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.function.Predicate;
    
    import com.java8.mod15.dati.*;
    
    public class TestCitta {
        
        public static void main(String args[]) {
            
            Citta milano = new Citta("Milano",true,false);
            Citta bari = new Citta("Bari",true,true);
            Citta foggia = new Citta("Foggia",false,false);
            Citta venezia = new Citta("Venezia",true,true);
            Citta roma = new Citta("Roma",true,false);
        
            List<Citta> listaCitta = new ArrayList<>();        
            listaCitta.add(milano);
            listaCitta.add(bari);
            listaCitta.add(foggia);
            listaCitta.add(venezia);
            listaCitta.add(roma);
            
    1      System.out.println("Lista città:\n" + getCittaFiltrate(listaCitta, TestCitta::getCitta));    
            
    2      public static List<Citta> getCittaFiltrate(List<Citta> listaCitta, Predicate<Citta> p) {
                final Iterator<Citta> i = listaCitta.iterator();
                while(i.hasNext()) {            
                    Citta citta = i.next();
    3               if(!p.test(citta)) {
                        i.remove();
                    }
                }
    4           return listaCitta;
            }
             
        }
        
        public static boolean getCitta(Citta citta) {
                return !"".equals(citta.toString());
        }
        
    }
    però mi vengono segnalati in corrispondenza delle righe che ho segnato rispettivamente questi problemi:
    1
    The method getCittaFiltrate(List<Citta>, TestCitta::getCitta) is undefined for the type TestCitta
    2
    Multiple markers at this line
    - p cannot be resolved to a variable
    - Illegal modifier for parameter $missing$; only final is permitted
    - Syntax error, insert ";" to complete Statement
    - Predicate cannot be resolved to a variable
    - Citta cannot be resolved to a variable
    - Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration
    - List cannot be resolved to a variable
    - Citta cannot be resolved to a variable
    - Syntax error, insert ";" to complete LocalVariableDeclarationStatement
    3
    p cannot be resolved
    4
    Void methods cannot return a value

    Non riesco a capire come risolvere questi problemi, sicuramente ho capito io poco sull'utilizzo delle interfacce funzionali del package java.util.function.

    Mi aiutate a capire?

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Beh, la prima cosa più evidente nel codice che hai postato è che le { } del main racchiudono anche il metodo getCittaFiltrate. Ovviamente non è valido, non è sintassi corretta.

    Poi comunque, a ben ragionare, il getCitta che fa da "predicato" verifica se la Citta ha un nome non vuoto. Siccome tutte le Citta che hai istanziato hanno un nome non vuoto, il predicato le prende tutte, ovvero in getCittaFiltrate nessuna Citta viene rimossa dal remove(). Quindi quale è il senso/utilità finale dell'esercizio?


    Buon Natale e Buone Feste a tutti!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Si praticamente ho fatto un altro errore stupido come prima, ho messo la definizione e il corpo di un metodo (getCittaFiltrate) all'interno di un altro metodo (main). Grazie per avermelo fatto notare.

    Per il resto l'esercizio ha solo lo scopo di stampare la lista delle città sfruttando i metodi a reference e l'interfaccia Predicate.



    p.s. dal punto di vista puramente discorsivo dire "metodi a reference" e dire "reference a metodi" è la stessa cosa?

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da newutente Visualizza il messaggio
    p.s. dal punto di vista puramente discorsivo dire "metodi a reference" e dire "reference a metodi" è la stessa cosa?
    "metodi a reference" non ha senso, non dice nulla di significativo. "reference a metodi" può avere senso in generale. Ma tieni presente che in Java, a livello di JVM, non esistono i riferimenti a metodi.

    L'espressione TestCitta::getCitta se noti viene sostanzialmente passata al parametro Predicate<Citta> p di getCittaFiltrate.
    Quello che succede è che a getCittaFiltrate viene passato un oggetto che in un qualche modo implementa la interfaccia Predicate e il cui metodo boolean test(T t) (dove T viene preso come Citta) contiene la invocazione al tuo metodo getCitta di TestCitta. Ma tutto questo viene fatto "dietro le quinte" dal compilatore.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Ma tieni presente che in Java, a livello di JVM, non esistono i riferimenti a metodi.
    e questo cosa comporta? Cioè se a livello di JVM non esistono i reference a metodi come fa il codice che contiene i reference a metodi ad essere "tradotto" in un linguaggio comprensibile dalla macchina?

    Quote Originariamente inviata da andbin Visualizza il messaggio
    L'espressione TestCitta::getCitta se noti viene sostanzialmente passata al parametro Predicate<Citta> p di getCittaFiltrate.
    Quello che succede è che a getCittaFiltrate viene passato un oggetto che in un qualche modo implementa la interfaccia Predicate e il cui metodo boolean test(T t) (dove T viene preso come Citta) contiene la invocazione al tuo metodo getCitta di TestCitta. Ma tutto questo viene fatto "dietro le quinte" dal compilatore.
    Vediamo se ho capito come funziona questa interfaccia funzionale Predicate.
    Se ho capito bene questa interfaccia permette semplicemente di fare dei controlli e restituire tramite l'unico metodo astratto test() un booleano.
    Per prima cosa c'è bisogno di un metodo che come parametro di input prenda un oggetto Predicate<T> e questo perchè all'interno del metodo bisogna richiamare su quell'oggetto il metodo test(). In poche parole quello che accade in getCittaFiltrate.
    Successivamente bisogna definire un altro metodo che deve restituire sempre un booleano, perchè appunto parliamo di controlli che lavorano su booleani. In poche parole quello che fa getCitta.
    Infine per utilizzare il tutto bisogna passare, durante la chiamata al metodo precedentemente creato che definisce un oggetto Predicate in input, il metodo creato per ultimo (il getCitta per intenderci) in modo da far capire al compilatore che tipo di controllo dovrà essere effettuato.
    Quindi diciamo che questa interfaccia permette di creare dei "filtri" al volo con poche righe di codice perchè è sufficiente passare poi al metodo (es. getCittaFiltrate) il "filtro" (es. getCitta).
    E' corretto?
    Ultima modifica di newutente; 30-12-2014 a 13:50

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da newutente Visualizza il messaggio
    e questo cosa comporta? Cioè se a livello di JVM non esistono i reference a metodi come fa il codice che contiene i reference a metodi ad essere "tradotto" in un linguaggio comprensibile dalla macchina?
    Perché c'è molto "dietro" le lambda expression e method reference! E il compilatore effettua un bel po' di cose di nascosto.

    Tieni presente che Java non è un linguaggio "funzionale". E non lo è ancora adesso, in senso stretto, nemmeno con Java 8. Nei linguaggi funzionali la "funzione" è un tipo di prima classe, che può essere passato, ritornato, assegnato alla stregua di altri tipi di dati.
    In Java no, non è così, almeno per il momento. Per introdurre lambda expression/method reference nel linguaggio hanno dovuto fare delle scelte, importanti e sicuramente non banali, più che altro per allinearsi a quello che è il type-system attuale di Java, fatto solo di primitivi e classi/interfacce(/enum/annotazioni, e anche array) e basta. Per farlo hanno tirato fuori innanzitutto il concetto di "interfaccia funzionale".
    Quando tu passi ad un metodo l'espressione TestCitta::getCitta, non stai passando (per ora, almeno in Java 8) un riferimento a getCitta! Sotto-sotto viene creato un oggetto che implementa la interfaccia indicata nel parametro, che deve avere il singolo metodo astratto che corrisponde, come forma, al tuo getCitta.

    Se vuoi andare molto a fondo in queste cose, allora es.:
    - Maurice Naftalin's Lambda FAQ
    - Java 8 Lambdas - A Peek Under the Hood
    - Java 8: The First Taste of Lambdas

    E questi comunque sono aspetti parecchio "avanzati" ....

    Quote Originariamente inviata da newutente Visualizza il messaggio
    Vediamo se ho capito come funziona questa interfaccia funzionale Predicate.
    In informatica (ma anche in logica matematica se non sbaglio) un "predicato" è una funzione che dato un valore X restituisce un booleano vero/falso. E l'uso più ovvio e naturale è per realizzare dei filtri al fine di accettare/rifiutare i valori.

    Quote Originariamente inviata da newutente Visualizza il messaggio
    Quindi diciamo che questa interfaccia permette di creare dei "filtri" al volo con poche righe di codice perchè è sufficiente passare poi al metodo (es. getCittaFiltrate) il "filtro" (es. getCitta).
    E' corretto?
    Detto così, si ok è corretto.

    Cerca anche di vedere la questione dell'inferenza dei tipi:

    - il parametro è Predicate<Citta>
    - Predicate ha un metodo astratto boolean test(T t) (questo è il metodo "funzionale")
    - quindi la firma da implementare è boolean test(Citta)
    - passi un "riferimento" (come descritto prima) ad un metodo public static boolean getCitta(Citta)

    Come vedi (parti in rosso) la forma corrisponde, quindi per il compilatore è ok.
    Il concetto vale per Predicate e per tutte le altre intefacce "funzionali".
    Ultima modifica di andbin; 30-12-2014 a 19:22
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Grazie per la spiegazione.
    Avrei una curiosità. Quando si utilizza l'espressione lambda non bisogna inserire il return altrimenti si ha un errore di sintassi, io però credo di aver interpretato male questa cosa perchè ho notato l'esatto contrario invece.
    Facendo un esempio questi sono i metodi di prima:
    codice:
    public class TestCitta {
        public static void main(String args[]) {
        ....
                
        System.out.println("Lista città:\n" + getCittaFiltrate(listaCitta, TestCitta::getCitta) + "\n");    
          
        System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, TestCitta::mare) + "\n");
         
        System.out.println("Lista capoluoghi:\n" + getCittaFiltrate(listaCitta, TestCitta::capoluogo) + "\n");
        
        }
        
        public static List<Citta> getCittaFiltrate(List<Citta> listaCitta, Predicate<Citta> p) {
            List<Citta> listaAppoggio = new ArrayList<>();
            final Iterator<Citta> i = listaCitta.iterator();
            while(i.hasNext()) {            
                Citta citta = i.next();
                if(p.test(citta)) {
                    listaAppoggio.add(citta);
                }
            }
            return listaAppoggio;
        }
        
       public static boolean getCitta(Citta citta) {
            return !"".equals(citta.toString());
       }
    
       public static boolean mare(Citta citta) {
            return citta.isDiMare() == true;
       }
        
       public static boolean capoluogo(Citta citta) {
            return citta.isCapoluogo() == true;
       }
    
    }
    se io anzichè il reference a metodi volessi utilizzare le espressioni lambda dovrei modificare quei system.out.println in questo modo:
    codice:
    System.out.println("Lista città:\n" + getCittaFiltrate(listaCitta, (citta) -> {return !"".equals(citta.toString());} ) + "\n");    
    System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, (citta) -> {return citta.isDiMare();}) + "\n");
    System.out.println("Lista capoluoghi:\n" + getCittaFiltrate(listaCitta, (citta) -> {return citta.isCapoluogo();}) + "\n");
    funziona perfettamente però i return li ho usati altrimenti otterrei un errore di sintassi perchè i metodi getCitta, mare e capoluogo restituiscono comunque qualcosa (in questi caso dei booleani).
    E' corretto quindi utilizzarli?

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Quote Originariamente inviata da newutente Visualizza il messaggio
    Avrei una curiosità. Quando si utilizza l'espressione lambda non bisogna inserire il return altrimenti si ha un errore di sintassi, io però credo di aver interpretato male questa cosa perchè ho notato l'esatto contrario invece.

    codice:
    System.out.println("Lista città:\n" + getCittaFiltrate(listaCitta, (citta) -> {return !"".equals(citta.toString());} ) + "\n");    
    System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, (citta) -> {return citta.isDiMare();}) + "\n");
    System.out.println("Lista capoluoghi:\n" + getCittaFiltrate(listaCitta, (citta) -> {return citta.isCapoluogo();}) + "\n");
    Il corpo di una lambda expression può essere: 1) una "espressione" oppure 2) un "blocco".

    Quindi:

    (citta) -> {return !"".equals(citta.toString());}

    e

    (citta) -> !"".equals(citta.toString())

    Sono assolutamente equivalenti.

    Ah, e per le regole delle lambda expression, se il parametro è uno solo e non è tipizzato esplicitamente, le parentesi ( ) possono anche essere omesse.
    Ultima modifica di andbin; 02-01-2015 a 22:14
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  9. #9
    Utente di HTML.it
    Registrato dal
    Oct 2014
    Messaggi
    315
    Ah ecco, nel momento in cui nel metodo "iniziale" c'è una return devo per forza utilizzare le parentesi graffe e il punto e virgola, oppure non inserisco la return ma devo anche eliminare parentesi graffe e punto e virgola.

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