JavaRush /Java Blog /Random-IT /Eliminare i loop in Java 8
KapChook
Livello 19
Volga

Eliminare i loop in Java 8

Pubblicato nel gruppo Random-IT
Lo stile funzionale introdotto in Java 8 è una grande aggiunta al linguaggio. Ora Java non è pura OOP, ora è un ibrido di OOP e programmazione funzionale. Questo è un punto di svolta e dobbiamo cambiare il nostro cervello OOP per assorbire questi cambiamenti. Eliminare i loop in Java 8 - 1Ma perché dovremmo accettare questi cambiamenti? Perché dovremmo perdere tempo cercando di andare d'accordo con uno stile funzionale quando possiamo risolvere il problema utilizzando la pura OOP?
  • Lo stile funzionale introdotto in Java 8 ci aiuta a ridurre il divario tra logica aziendale e codice. Ci permette di raccontare la storia in un flusso naturale a un livello superiore. Invece di dire come vuoi farlo, puoi dire cosa vuoi fare.

  • Il codice diventa più pulito e conciso.

  • Le funzioni di ordine elevato ci permettono di:

    • Invia funzioni ad altre funzioni
    • Creare funzioni all'interno di altre funzioni
    • Restituisce funzioni da altre funzioni

    Questa è una grande vittoria per Java, poiché per farlo dobbiamo inviare, creare e restituire oggetti. Saremo in grado di scrivere codice più affidabile, mirato e più facile da riutilizzare.

  • Grazie ai lambda possiamo fare calcoli pigri. Quando un'espressione lambda viene inviata come argomento del metodo, il compilatore la valuterà quando verrà chiamata nel metodo. Questo è diverso dagli argomenti del metodo normale, che vengono valutati immediatamente.

  • I lambda rendono divertente la scrittura dei test unitari. Ci consentono di creare test leggeri, puliti, di piccole dimensioni e veloci da scrivere. Possiamo sradicare il codice in prova utilizzando lambda. Questo ci consente di testare come tutti i tipi di scenari influenzeranno il codice.

  • Nuovi modelli da imparare.

  • E altro ancora!

Ma basta acqua, in questo articolo daremo uno sguardo alle soluzioni alternative ai cicli tradizionali. Naturalmente i cicli sono flessibili, ma ciò ha un prezzo. break, cambiano radicalmente il comportamento del ciclo, costringendoci a capire non solo cosa il codice sta cercando di ottenere, continuema returnanche come funziona il ciclo. Ora daremo un'occhiata a come possiamo trasformare i loop in codice più conciso e leggibile.

Che la codifica abbia inizio!

Lavoreremo con articoli. Un articolo ha un titolo, un autore e diversi tag.
private class Article {

    private final String title;
    private final String author;
    private final List<String> tags;

    private Article(String title, String author, List<String> tags) {
        this.title = title;
        this.author = author;
        this.tags = tags;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public List<String> getTags() {
        return tags;
    }
}
Ogni esempio conterrà una soluzione tradizionale che utilizza i loop e una soluzione che utilizza le nuove funzionalità di Java 8. Nel primo esempio, vogliamo trovare il primo articolo della raccolta con il tag “Java”. Diamo un'occhiata a una soluzione utilizzando un ciclo.
public Article getFirstJavaArticle() {

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            return article;
        }
    }
    return null;
}
Ora risolviamo il problema utilizzando le operazioni dell'API Stream.
public Optional<Article> getFirstJavaArticle() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .findFirst();
    }
Abbastanza bello, non è vero? Utilizziamo innanzitutto l'operazione filterper trovare tutti gli articoli con il tag “Java”, quindi utilizziamo findFirst()per ottenere la prima occorrenza. Poiché i flussi sono lenti e il filtro restituisce un flusso, questo approccio elaborerà solo gli elementi finché non troverà la prima corrispondenza. Ora inseriamo tutti gli articoli contrassegnati con "Java" anziché solo il primo. Innanzitutto la soluzione utilizzando i loop.
public List<Article> getAllJavaArticles() {

    List<Article> result = new ArrayList<>();

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            result.add(article);
        }
    }
    return result;
}
Soluzione che utilizza operazioni di flusso.
public List<Article> getAllJavaArticles() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .collect(Collectors.toList());
    }
In questo esempio abbiamo utilizzato un'operazione collectper abbreviare il flusso risultante, anziché dichiarare una raccolta e aggiungere esplicitamente le voci corrispondenti. Fin qui tutto bene. È tempo di esempi che faranno davvero brillare l'API Stream. Raggruppiamo tutti gli articoli per autore. Come al solito, iniziamo risolvendolo utilizzando i loop:
public Map<String, List<Article>> groupByAuthor() {

    Map<String, List<Article>> result = new HashMap<>();

    for (Article article : articles) {
        if (result.containsKey(article.getAuthor())) {
            result.get(article.getAuthor()).add(article);
        } else {
            ArrayList<Article> articles = new ArrayList<>();
            articles.add(article);
            result.put(article.getAuthor(), articles);
        }
    }
    return result;
}
Possiamo trovare una soluzione pulita a questo problema utilizzando le operazioni di flusso?
public Map<String, List<Article>> groupByAuthor() {
    return articles.stream()
        .collect(Collectors.groupingBy(Article::getAuthor));
}
Sorprendente! Utilizzando un'operazione groupingBye un riferimento al metodo getAuthor(), otteniamo un codice pulito e leggibile. Ora troviamo il resto dei tag utilizzati nella raccolta. Iniziamo con un esempio di ciclo:
public Set<String> getDistinctTags() {

    Set<String> result = new HashSet<>();

    for (Article article : articles) {
        result.addAll(article.getTags());
    }
    return result;
}
Ok, diamo un'occhiata a come possiamo risolvere questo problema utilizzando le operazioni di flusso:
public Set<String> getDistinctTags() {
    return articles.stream()
        .flatMap(article -> article.getTags().stream())
        .collect(Collectors.toSet());
}
Freddo! flatmapci aiuta ad appiattire l'elenco di tag in un unico flusso di risultati, che poi utilizziamo collectper creare il set restituito.

Possibilità infinite

Questi erano 4 esempi di come i loop possono essere sostituiti con codice più leggibile. Assicurati di controllare l'API Stream, poiché questo articolo ha solo scalfito la superficie. Padroneggiare il nuovo stile funzionale di Java sarà una sfida per gli sviluppatori OOP, ma è una sfida che dovrebbe essere ben accolta. Andrò anche oltre e dirò che dovresti imparare un linguaggio di programmazione puramente funzionale. In questo modo puoi comprendere appieno le capacità e la potenza che fornisce. Penso che questo ti aiuterà a comprendere la programmazione funzionale a un livello diverso. Quindi impara la programmazione funzionale insieme al buon vecchio OOP e usali entrambi per scrivere un codice ancora migliore! Un mix gratuito di traduzioni di due articoli: Perché dovresti abbracciare la programmazione funzionale in Java 8 e Swerving Away from Loops in Java 8
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION