Πώς να μάθετε το Java Stream API [+5 Resources]

Μια ροή στην Java είναι μια ακολουθία στοιχείων στα οποία μπορούν να εκτελεστούν διαδοχικές ή παράλληλες λειτουργίες.

Μπορεί να υπάρξει ένας αριθμός “n” ενδιάμεσων λειτουργιών και, επιτέλους, μια λειτουργία τερματικού, μετά την οποία επιστρέφεται το αποτέλεσμα.

Τι είναι το Stream;

Η διαχείριση των ροών μπορεί να γίνει από το Stream API, το οποίο εισήχθη στην Java 8.

Φανταστείτε το Stream ως έναν αγωγό παραγωγής στον οποίο ορισμένα αγαθά πρέπει να κατασκευαστούν, να ταξινομηθούν και στη συνέχεια να συσκευαστούν για αποστολή. Στην Java, αυτά τα αγαθά είναι αντικείμενα ή συλλογές αντικειμένων, οι λειτουργίες είναι η κατασκευή, η ταξινόμηση και η συσκευασία και ο αγωγός είναι η ροή.

Τα συστατικά ενός ρεύματος είναι:

  • Μια αρχική εισαγωγή
  • Ενδιάμεσες λειτουργίες
  • Λειτουργία τερματικού
  • Τελικό αποτέλεσμα

Ας εξερευνήσουμε ορισμένα χαρακτηριστικά μιας ροής σε Java:

  • Η ροή δεν είναι μια δομή δεδομένων στη μνήμη. Μάλλον, είναι μια ακολουθία πινάκων, αντικειμένων ή συλλογών αντικειμένων που λειτουργούν με ορισμένες μεθόδους.
  • Οι ροές έχουν δηλωτικό χαρακτήρα, δηλ. καθορίζετε τι να κάνετε αλλά όχι πώς να το κάνετε.
  • Μπορούν να καταναλωθούν μόνο μία φορά καθώς δεν αποθηκεύονται πουθενά.
  • Η ροή δεν τροποποιεί την αρχική δομή δεδομένων. αντλεί μόνο μια νέα δομή από αυτό.
  • Επιστρέφει το τελικό αποτέλεσμα που προέκυψε από την τελική μέθοδο σε εξέλιξη.

API ροής έναντι επεξεργασίας συλλογών

Μια συλλογή είναι μια δομή δεδομένων στη μνήμη που αποθηκεύει και επεξεργάζεται δεδομένα. Οι συλλογές παρέχουν δομές δεδομένων όπως Set, Map, List, κ.λπ., για την αποθήκευση δεδομένων. Από την άλλη πλευρά, μια ροή είναι ένας τρόπος για την αποτελεσματική μεταφορά δεδομένων μετά την επεξεργασία τους μέσω ενός αγωγού.

Ακολουθεί ένα παράδειγμα συλλογής ArrayList:-

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(0, 3);
        System.out.println(list);
    }
}

Output: 
[3]

Όπως μπορείτε να δείτε στο παραπάνω παράδειγμα, μπορείτε να δημιουργήσετε μια συλλογή ArrayList, να αποθηκεύσετε δεδομένα σε αυτήν και στη συνέχεια να λειτουργήσετε σε αυτά τα δεδομένα χρησιμοποιώντας διαφορετικές μεθόδους.

  Πώς να προσθέσετε ένα πλαίσιο ελέγχου σε ένα Έγγραφο Google

Χρησιμοποιώντας μια ροή, μπορείτε να λειτουργήσετε σε μια υπάρχουσα δομή δεδομένων και να επιστρέψετε μια νέα τροποποιημένη τιμή. Παρακάτω είναι ένα παράδειγμα δημιουργίας μιας συλλογής ArrayList και φιλτραρίσματος χρησιμοποιώντας μια ροή.

import java.util.ArrayList;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList();

        for (int i = 0; i < 20; i++) {
            list.add(i+1);
        }

        System.out.println(list);

        Stream<Integer> filtered = list.stream().filter(num -> num > 10);
        filtered.forEach(num -> System.out.println(num + " "));
    }
}

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

Στο παραπάνω παράδειγμα, δημιουργείται μια ροή χρησιμοποιώντας την υπάρχουσα λίστα και η λίστα επαναλαμβάνεται για να φιλτράρει τιμές μεγαλύτερες από 10. Σημειώστε ότι η ροή δεν αποθηκεύει τίποτα, η λίστα απλώς επαναλαμβάνεται και το αποτέλεσμα εκτυπώνεται. Εάν προσπαθήσετε να εκτυπώσετε τη ροή, θα λάβετε μια αναφορά στη ροή αντί για τιμές.

Εργασία σε Java Stream API

Το Java Stream API λαμβάνει μια συλλογή πηγών στοιχείων ή μια ακολουθία στοιχείων και στη συνέχεια εκτελεί λειτουργίες σε αυτά για να εξαγάγει ένα τελικό αποτέλεσμα. Ένα ρεύμα είναι απλώς ένας αγωγός μέσω του οποίου διέρχεται μια ακολουθία στοιχείων και μετασχηματίζεται με κάποιο τρόπο.

Μια ροή μπορεί να δημιουργηθεί από διάφορες πηγές, όπως:

  • Μια συλλογή όπως μια λίστα ή ένα σύνολο.
  • Μια συστοιχία.
  • Από τα αρχεία και τις διαδρομές τους με χρήση buffer.

Υπάρχουν δύο τύποι λειτουργιών που εκτελούνται σε μια ροή:-

  • Ενδιάμεσες Λειτουργίες
  • Λειτουργίες Τερματικού

Λειτουργίες ενδιάμεσου έναντι τερματικού

Κάθε ενδιάμεση λειτουργία επιστρέφει μια νέα ροή εσωτερικά η οποία μετατρέπει την είσοδο χρησιμοποιώντας την καθορισμένη μέθοδο. Τίποτα δεν διασχίζεται στην πραγματικότητα. Αντίθετα, περνάει στο επόμενο ρεύμα. Μόνο στη λειτουργία τερματικού διασχίζεται το ρεύμα για να ληφθεί το επιθυμητό αποτέλεσμα.

Για παράδειγμα, έχετε μια λίστα με 10 αριθμούς που θέλετε να φιλτράρετε και στη συνέχεια να αντιστοιχίσετε σε κάτι. Δεν θα διασχιστεί αμέσως κάθε στοιχείο της λίστας για να ληφθεί το φιλτραρισμένο αποτέλεσμα και να αντιστοιχιστεί σε κάτι άλλο. Αντίθετα, θα ελέγχονται μεμονωμένα στοιχεία και εάν πληρούν την προϋπόθεση, θα αντιστοιχίζονται. Νέες ροές για κάθε στοιχείο.

Η λειτουργία χάρτη θα εκτελεστεί σε μεμονωμένα στοιχεία που ικανοποιούν το φίλτρο και όχι ολόκληρη τη λίστα. Και τη στιγμή της λειτουργίας του τερματικού, διασχίζονται και συνδυάζονται σε ένα ενιαίο αποτέλεσμα.

  Πώς να αφαιρέσετε τον εαυτό σας από το Διαδίκτυο

Μετά την εκτέλεση της λειτουργίας τερματικού, το ρεύμα καταναλώνεται και δεν μπορεί πλέον να χρησιμοποιηθεί περαιτέρω. Πρέπει να δημιουργήσετε μια νέα ροή για να εκτελέσετε ξανά τις ίδιες λειτουργίες.

Πηγή: The Bored Dev

Με μια κατανόηση σε επίπεδο επιφάνειας του τρόπου λειτουργίας των ροών, ας μεταβούμε στις λεπτομέρειες υλοποίησης των ροών σε Java.

#1. Ένα Κενό Ρεύμα

Δημιουργήστε μια κενή ροή χρησιμοποιώντας την κενή μέθοδο του Stream API.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream emptyStream = Stream.empty();
        System.out.println(emptyStream.count());
    }
}

Output:
0

Εδώ, εάν εκτυπώσετε τον αριθμό των στοιχείων σε αυτήν τη ροή, λαμβάνετε 0 ως έξοδο επειδή είναι μια κενή ροή χωρίς στοιχεία. Οι κενές ροές είναι πολύ χρήσιμες για την αποφυγή εξαιρέσεων μηδενικού δείκτη.

#2. Ροή από τις Συλλογές

Συλλογές όπως το Lists και το Set εκθέτουν μια μέθοδο stream() που σας επιτρέπει να δημιουργήσετε μια ροή από μια συλλογή. Στη συνέχεια, η ροή που δημιουργήθηκε μπορεί να διασχιστεί για να ληφθεί το τελικό αποτέλεσμα.

ArrayList<Integer> list = new ArrayList();

for (int i = 0; i < 20; i++) {
    list.add(i+1);
}

System.out.println(list);

Stream<Integer> filtered = list.stream().filter(num -> num > 10);
filtered.forEach(num -> System.out.println(num + " "));

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

#3. Ροή από Arrays

Η μέθοδος Arrays.stream() χρησιμοποιείται για τη δημιουργία μιας ροής από έναν πίνακα.

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] stringArray = new String[]{"this", "is", "grtechpc.org"};
        Arrays.stream(stringArray).forEach(item -> System.out.print(item + " "));
    }
}

#Output

this is grtechpc.org 

Μπορείτε επίσης να καθορίσετε τον αρχικό και τον τελικό δείκτη των στοιχείων για να δημιουργήσετε μια ροή. Το αρχικό ευρετήριο είναι περιεκτικό, ενώ το τελικό ευρετήριο είναι αποκλειστικό.

String[] stringArray = new String[]{"this", "is", "grtechpc.org"};
Arrays.stream(stringArray, 1, 3).forEach(item -> System.out.print(item + " "));

Output:
is grtechpc.org

#4. Εύρεση ελάχιστων και μέγιστων αριθμών χρησιμοποιώντας Ροές

Η πρόσβαση στον μέγιστο και ελάχιστο αριθμό μιας συλλογής ή ενός πίνακα μπορεί να γίνει με τη χρήση Comparators σε Java. Οι μέθοδοι min() και max() δέχονται έναν συγκριτή και επιστρέφουν ένα Προαιρετικό αντικείμενο.

Ένα προαιρετικό αντικείμενο είναι ένα αντικείμενο κοντέινερ που μπορεί να περιέχει ή να μην περιέχει μια μη μηδενική τιμή. Εάν περιέχει μια μη μηδενική τιμή, η κλήση της μεθόδου get() σε αυτήν θα επιστρέψει την τιμή.

import java.util.Arrays;
import java.util.Optional;

public class MinMax {
    public static void main(String[] args) {
        Integer[] numbers = new Integer[]{21, 82, 41, 9, 62, 3, 11};

        Optional<Integer> maxValue = Arrays.stream(numbers).max(Integer::compare);
        System.out.println(maxValue.get());

        Optional<Integer> minValue = Arrays.stream(numbers).min(Integer::compare);
        System.out.println(minValue.get());
    }
}

#Output
82
3

Πόροι μάθησης

Τώρα που έχετε μια βασική κατανόηση των ροών σε Java, ακολουθούν 5 πόροι για να εξοικειωθείτε καλά με την Java 8:

  11 Μετατροπέας δυαδικού σε κείμενο για γνώση

#1. Java 8 σε δράση

Αυτό το βιβλίο είναι ένας οδηγός που παρουσιάζει νέα χαρακτηριστικά της Java 8, συμπεριλαμβανομένων ροών, λάμδα και προγραμματισμού λειτουργικού στυλ. Κουίζ και ερωτήσεις ελέγχου γνώσεων αποτελούν επίσης μέρος του βιβλίου, που θα σας βοηθήσουν να ανακτήσετε όσα μάθατε.

Μπορείτε να αποκτήσετε αυτό το βιβλίο σε μορφή χαρτόδετο καθώς και σε μορφή ηχητικού βιβλίου στο Amazon.

#2. Java 8 Lambdas: Functional Programming For The Masses

Αυτό το βιβλίο έχει σχεδιαστεί ειδικά για να διδάξει τους βασικούς προγραμματιστές Java SE πώς η προσθήκη εκφράσεων Lambda επηρεάζει τη γλώσσα Java. Περιλαμβάνει ρευστές επεξηγήσεις, ασκήσεις κώδικα και παραδείγματα για να κατακτήσετε τις εκφράσεις λάμδα Java 8.

Είναι διαθέσιμο σε μορφή χαρτόδετου και έκδοσης Kindle στο Amazon.

#3. Java SE 8 για τους πραγματικά ανυπόμονους

Εάν είστε έμπειρος προγραμματιστής Java SE, αυτό το βιβλίο θα σας καθοδηγήσει στις βελτιώσεις που έγιναν στο Java SE 8, το API ροής, την προσθήκη εκφράσεων λάμδα, βελτιώσεις στον ταυτόχρονο προγραμματισμό σε Java και ορισμένες λειτουργίες Java 7 που οι περισσότεροι άνθρωποι δεν έχουν δεν ξέρω για.

Είναι διαθέσιμο μόνο σε μορφή χαρτόδετου στο Amazon.

#4. Μάθετε Java Functional Programming με Lambdas & Streams

Αυτό το μάθημα από την Udemy διερευνά τις βασικές αρχές του λειτουργικού προγραμματισμού σε Java 8 και 9. Εκφράσεις λάμδα, αναφορές μεθόδων, ροές και λειτουργικές διεπαφές είναι οι έννοιες στις οποίες εστιάζει αυτό το μάθημα.

Περιλαμβάνει επίσης ένα σωρό παζλ Java και ασκήσεις που σχετίζονται με τον λειτουργικό προγραμματισμό.

#5. Java Class Library

Η Java Class Library είναι μέρος της Εξειδίκευσης Core Java που προσφέρεται από την Coursera. Θα σας διδάξει πώς να γράφετε κώδικα ασφαλείας τύπου χρησιμοποιώντας Java Generics, να κατανοείτε τη βιβλιοθήκη της τάξης που αποτελείται από περισσότερες από 4000 τάξεις, πώς να εργάζεστε με αρχεία και να χειρίζεστε σφάλματα χρόνου εκτέλεσης. Ωστόσο, υπάρχουν ορισμένες προϋποθέσεις για να παρακολουθήσετε αυτό το μάθημα:

  • Εισαγωγή στη Java
  • Εισαγωγή στον Αντικειμενοστραφή Προγραμματισμό με Java
  • Αντικειμενοστρεφείς ιεραρχίες στην Java

Τελικές Λέξεις

Το Java Stream API και η εισαγωγή των λειτουργιών Lambda στην Java 8 απλοποίησαν και βελτίωσαν πολλά πράγματα στην Java, όπως η παράλληλη επανάληψη, οι λειτουργικές διεπαφές, ο λιγότερος κώδικας κ.λπ.

Ωστόσο, τα ρεύματα έχουν ορισμένους περιορισμούς. Ο μεγαλύτερος περιορισμός τους είναι ότι μπορούν να καταναλωθούν μόνο μία φορά. Εάν είστε προγραμματιστής Java, οι πόροι που αναφέρονται παραπάνω μπορούν να σας βοηθήσουν να κατανοήσετε αυτά τα θέματα με πολύ περισσότερες λεπτομέρειες, οπότε φροντίστε να τα ελέγξετε.

Μπορεί επίσης να θέλετε να μάθετε για τον χειρισμό εξαιρέσεων στην Java.