Hur man lär sig Java Stream API [+5 Resources]

En ström i Java är en sekvens av element på vilka sekventiella eller parallella operationer kan utföras.

Det kan finnas ett ”n” antal mellanoperationer och till sist en terminaloperation, varefter resultatet returneras.

Vad är en Stream?

Strömmar kan hanteras av Stream API, som introducerades i Java 8.

Föreställ dig Stream som en tillverkningspipeline där vissa varor måste tillverkas, sorteras och sedan packas för transport. I Java är dessa varor föremål eller samlingar av föremål, operationerna är tillverkning, sortering och packning, och pipelinen är strömmen.

Komponenterna i en ström är:

  • En första ingång
  • Mellanliggande operationer
  • Terminaldrift
  • Slutresultat

Låt oss utforska några funktioner i en ström i Java:

  • Stream är inte en datastruktur i minnet; snarare är det en sekvens av arrayer, objekt eller samlingar av objekt som manövreras med vissa metoder.
  • Strömmar är deklarativa till sin natur, dvs du anger vad som ska göras men inte hur det ska göras.
  • De kan endast konsumeras en gång eftersom de inte förvaras någonstans.
  • Stream ändrar inte den ursprungliga datastrukturen; den härleder bara en ny struktur från den.
  • Den returnerar slutresultatet från den slutliga metoden i pipelinen.

Stream API vs. samlingsbearbetning

En samling är en datastruktur i minnet som lagrar och bearbetar data. Samlingar tillhandahåller datastrukturer som Set, Map, List, etc., för att lagra data. Å andra sidan är en ström ett sätt att effektivt överföra data efter att ha bearbetat det genom en pipeline.

Här är ett exempel på en ArrayList-samling:

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]

Som du kan se i exemplet ovan kan du skapa en ArrayList-samling, lagra data i den och sedan arbeta på den datan med olika metoder.

Med hjälp av en ström kan du arbeta på en befintlig datastruktur och returnera ett nytt ändrat värde. Nedan är ett exempel på hur man skapar en ArrayList-samling och filtrerar den med en ström.

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 

I exemplet ovan skapas en ström med den befintliga listan och listan upprepas för att filtrera värden större än 10. Observera att strömmen inte lagrar någonting, listan upprepas bara och resultatet skrivs ut. Om du försöker skriva ut strömmen får du en referens till strömmen istället för värden.

Arbetar med Java Stream API

Java Stream API tar in en källsamling av element eller en sekvens av element och utför sedan operationer på dem för att få ett slutresultat. En ström är bara en rörledning genom vilken en sekvens av element passerar och omvandlas på något sätt.

En ström kan skapas från olika källor, inklusive:

  • En samling som en lista eller uppsättning.
  • En uppsättning.
  • Från filer och deras sökvägar med hjälp av en buffert.

Det finns två typer av operationer som utförs i en ström:-

  • Mellanliggande verksamhet
  • Terminaldrift

Mellanliggande kontra terminaldrift

Varje mellanoperation returnerar en ny ström internt som transformerar indata med den angivna metoden. Ingenting korsas faktiskt; Istället förs den vidare till nästa ström. Det är först vid terminaloperationen som strömmen genomkorsas för att få önskat resultat.

Du har till exempel en lista med 10 nummer som du vill filtrera bort och sedan mappa till något. Inte alla element i listan kommer att passeras omedelbart för att få det filtrerade resultatet och mappa det till något annat. Istället kommer enskilda element att kontrolleras, och om de uppfyller villkoret, mappas de. Nya strömmar för varje element.

Kartoperationen kommer att utföras på enskilda objekt som uppfyller filtret och inte hela listan. Och vid tidpunkten för terminaloperationen korsas de och kombineras till ett enda resultat.

Efter att ha utfört terminaloperationen förbrukas strömmen och kan inte längre användas ytterligare. Du måste skapa en ny ström för att utföra samma operationer igen.

Källa: The Bored Dev

Med en förståelse på ytan av hur strömmar fungerar, låt oss gå in i implementeringsdetaljerna för strömmar i Java.

#1. En tom ström

Skapa en tom ström genom att använda den tomma metoden i 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

Här, om du skriver ut antalet element i denna ström, får du 0 som utdata eftersom det är en tom ström utan element. Tomma strömmar är till stor hjälp för att undvika undantag för nollpekare.

#2. Streama från samlingar

Samlingar som Lists och Set visar en stream()-metod som låter dig skapa en stream från en samling. Den skapade strömmen kan sedan korsas för att få slutresultatet.

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. Streama från Arrays

Metoden Arrays.stream() används för att skapa en ström från en array.

import java.util.Arrays;

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

#Output

this is adminvista.com 

Du kan också ange start- och slutindex för elementen att skapa en ström av. Startindexet är inklusive, medan slutindexet är exklusivt.

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

Output:
is adminvista.com

#4. Hitta min- och maxtal med Streams

Att komma åt det maximala och lägsta antalet för en samling eller en array kan göras genom att använda komparatorer i Java. Metoderna min() och max() accepterar en komparator och returnerar ett Optional-objekt.

Ett valfritt objekt är ett containerobjekt som kan innehålla ett icke-nullvärde eller inte. Om den innehåller ett icke-nullvärde, returneras värdet genom att anropa get()-metoden på det.

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

Lärresurser

Nu när du har en grundläggande förståelse för strömmar i Java, här är 5 resurser för dig att bli väl bevandrad i Java 8:

#1. Java 8 i aktion

Den här boken är en guide som visar upp nya funktioner i Java 8, inklusive streams, lambdas och programmering av funktionell stil. Frågesporter och kunskapskontrollfrågor är också en del av boken, som hjälper dig att återställa det du lärt dig.

Du kan få den här boken i pocketformat såväl som i ljudboksformat på Amazon.

#2. Java 8 Lambdas: Funktionell programmering för massorna

Den här boken är speciellt utformad för att lära grundläggande Java SE-utvecklare hur tillägget av Lambda-uttryck påverkar Java-språket. Den innehåller flytande förklaringar, kodövningar och exempel för att du ska kunna bemästra Java 8 lambda-uttryck.

Den finns i pocketformat och Kindle-utgåvan på Amazon.

#3. Java SE 8 för den riktigt otåliga

Om du är en erfaren Java SE-utvecklare, kommer den här boken att guida dig genom förbättringarna som gjorts i Java SE 8, stream-API:et, tillägget av lambda-uttryck, förbättringar av samtidig programmering i Java och vissa Java 7-funktioner som de flesta människor har. vet inte om.

Den är endast tillgänglig i pocketformat på Amazon.

#4. Lär dig Java funktionell programmering med Lambdas & Streams

Denna kurs av Udemy utforskar grunderna för funktionell programmering i Java 8 och 9. Lambdauttryck, metodreferenser, strömmar och funktionella gränssnitt är begreppen som denna kurs fokuserar på.

Den innehåller också ett gäng Java-pussel och övningar relaterade till funktionell programmering.

#5. Java klassbibliotek

Java Class Library är en del av Core Java Specialization som erbjuds av Coursera. Den kommer att lära dig hur man skriver typsäker kod med Java Generics, förstår klassbiblioteket som består av över 4000 klasser, hur man arbetar med filer och hanterar runtime-fel. Det finns dock några förutsättningar för att ta denna kurs:

  • Introduktion till Java
  • Introduktion till objektorienterad programmering med Java
  • Objektorienterade hierarkier i Java

Slutord

Java Stream API och införandet av Lambda-funktioner i Java 8 förenklade och förbättrade många saker i Java, såsom parallell iteration, funktionella gränssnitt, mindre kod, etc.

Strömmar har dock vissa begränsningar; deras största begränsning är att de bara kan konsumeras en gång. Om du är en Java-utvecklare kan resurserna som nämns ovan hjälpa dig att förstå dessa ämnen i mycket mer detalj, så se till att kolla in dem.

Du kanske också vill veta om undantagshantering i Java.