Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  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
    Quote Originariamente inviata da andbin Visualizza il messaggio
    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.
    Grazie per la spiegazione.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    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" ....
    sono aspetti un tantino avanzati e per il momento vorrei tralasciarli però grazie per i link.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    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.


    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".
    Ah ecco, quindi è un discorso valido per tutte le interfacce funzionali. Per certi versi potrei seguire quindi questo "schema" per chiarirmi le idee non solo su Predicate.

    Tornando all'esercizio devo stampare la lista delle città di mare. Questo è il codice:
    codice:
    public static void main(String args[]) {
    ...
            System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, TestCitta::mare) + "\n");
    }    
    
    public static List<Citta> getCittaFiltrate(List<Citta> listaCitta, Predicate<Citta> p) {
            final Iterator<Citta> i = listaCitta.iterator();
            while(i.hasNext()) {            
                Citta citta = i.next();
                if(!p.test(citta)) {
                    i.remove();
                }
            }
            return listaCitta;
    }
        
    public static boolean mare(Citta citta) {
            return "true".equals(citta.isDiMare());
    }
    Il problema è che stampa sempre una lista vuota perchè anche nel momento in cui va a selezionare una città di mare (es. Bari e Venezia) non riconosce "true" ma "false" e quindi viene lanciato remove() che rimuove l'elemento selezionato dall'iteratore.
    Non vorrei che sia un altro errore stupido che non riesco a correggere.
    Ultima modifica di newutente; 30-12-2014 a 20:28

  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
    codice:
    public static boolean mare(Citta citta) {
            return "true".equals(citta.isDiMare());
    }

    Non vorrei che sia un altro errore stupido che non riesco a correggere.
    Ehm ... purtroppo sì, invece. "true" è un String è il equals è il suo, di String. Ma stai passando come argomento un Boolean (autoboxato da boolean). Il equals riceve in generale un Object ma è tipico per le classi verificare che l'oggetto sia dello stesso tipo (tipicamente con instanceof). E String quindi non accetta un Boolean!

    Banalmente si potrebbe fare

    return citta.isDiMare() == true;

    o ancora più semplice:

    return citta.isDiMare();

    che non cambia nulla nel significato.


    Ma c'è di più. Tu hai creato un metodo statico che riceve un Citta e su quest'ultimo invochi un metodo di istanza isDiMare(). Di per sé non servirebbe ... bastarebbe invocare

    System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, Citta::isDiMare) + "\n");
    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
    Quote Originariamente inviata da andbin Visualizza il messaggio
    Ehm ... purtroppo sì, invece. "true" è un String è il equals è il suo, di String. Ma stai passando come argomento un Boolean (autoboxato da boolean). Il equals riceve in generale un Object ma è tipico per le classi verificare che l'oggetto sia dello stesso tipo (tipicamente con instanceof). E String quindi non accetta un Boolean!

    Banalmente si potrebbe fare

    return citta.isDiMare() == true;

    o ancora più semplice:

    return citta.isDiMare();

    che non cambia nulla nel significato.
    accidenti che errore. grazie per avermelo fatto notare.

    Quote Originariamente inviata da andbin Visualizza il messaggio
    Ma c'è di più. Tu hai creato un metodo statico che riceve un Citta e su quest'ultimo invochi un metodo di istanza isDiMare(). Di per sé non servirebbe ... bastarebbe invocare

    System.out.println("Lista città di mare:\n"+ getCittaFiltrate(listaCitta, Citta::isDiMare) + "\n");
    e questo posso farlo perchè il metodo isDiMare restituisce un boolean e quindi è "compatibile" con Predicate?

  10. #10
    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 posso farlo perchè il metodo isDiMare restituisce un boolean e quindi è "compatibile" con Predicate?
    Per i metodi (non conto ora la forma per i costruttori) i method reference possono avere in generale tre forme:

    object::instanceMethod
    Class::staticMethod
    Class::instanceMethod

    I primi due casi sono equivalenti ad avere una lambda expression che ha tanti parametri quanti sono quelli del metodo.
    Es.

    Math::max è equivalente ad una lambda expression (a, b) -> Math.max(a, b)

    Perché il metodo max ha due parametri (ci sono 4 versioni in overload, con tipi differenti ... quale verrebbe scelto dipende ovviamente dal contesto e dalla inferenza dei tipi).

    Mentre il terzo caso è equivalente ad una lambda expression in cui il primo parametro è il "target" del metodo referenziato.
    Es.

    Citta::isDiMare è equivalente alla lambda expression (c) -> c.isDiMare()

    E quest'ultima corrisponde al boolean test(Citta) di Predicate<Citta> perché riceve un parametro (Citta per inferenza) e l'espressione c.isDiMare() dà un boolean.
    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 © 2025 vBulletin Solutions, Inc. All rights reserved.