Stream-API i Java
Det finns olika sätt att bearbeta data i Java – loopar, metoder och olika algoritmer. Men i Java 8 introducerades ett mycket kraftfullt verktyg – Stream API.
Enkelt uttryckt är Stream API ett sätt att arbeta snabbt och enkelt med en ström av information. I vårt fall representeras denna informationsström av samlingar. Stream API har vissa begrepp. Här är de viktigaste.
Huvudbegrepp
-
Stream: representerar en sekvens av dataelement som kan bearbetas;
-
Intermediära operationer: operationer som skapar en ny stream efter att de har utförts. Exempel:
filter,map,distinct,sorted; -
Terminala operationer: operationer som avslutar bearbetningen av streamen och returnerar ett resultat. Exempel:
collect,forEach,count,reduce; -
Parallella streams: möjliggör parallell bearbetning av data. Metoderna
parallel()ochparallelStream()används för att skapa parallella streams.
Nog med teori, låt oss börja koda!
En stream deklareras genom att använda en metod på den samling du vill omvandla till en stream:
Main.java
12List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream();
Med metoden stream() erhålls en stream av strängar. För att börja arbeta med streamen behöver vi dock förstå vad lambda-uttryck är, eftersom stream-metoder huvudsakligen använder dessa.
Lambda-uttryck
Lambda-uttryck introducerades i Java 8 och representerar en förenklad form av att skapa anonyma funktioner i Java. Vi har inte behandlat anonyma funktioner tidigare eftersom de inte varit särskilt nödvändiga, men nu kommer vi att bekanta oss med dem genom lambda-uttryck.
Syntax för lambda-uttryck:
Den allmänna syntaxen för lambda-uttryck i Java ser ut så här:
Example.java
123(parameters) -> expression // or (parameters) -> { statements; }
-
Parametrar: detta är en parameterlista som kan vara tom eller innehålla en eller flera parametrar;
-
Pil: representeras av symbolen
->, som separerar parametrarna från kroppen av lambda-uttrycket; -
Uttryck eller satser: detta är funktionens kropp, som innehåller ett uttryck eller ett block av satser.
Här är ett exempel på ett lambda-uttryck som representerar en enkel funktion som adderar två tal:
Example.java
12345678910// Traditional way MathOperation addition = new MathOperation() { @Override public int operate(int a, int b) { return a + b; } }; // Using a lambda expression MathOperation addition = (int a, int b) -> a + b;
Låt oss titta närmare på vad som faktiskt händer i koden ovan och hur vi använder lambda-uttryck:
Main.java
1234567891011121314package com.example; // Functional interface with a single abstract method interface MyMathOperation { int operate(int a, int b); } public class Main { public static void main(String[] args) { // Using a lambda expression to implement the interface MyMathOperation addition = (a, b) -> a + b; System.out.println("Sum: " + addition.operate(5, 3)); } }
I koden ovan:
En funktionell gränssnitt MyMathOperation skapades med en enda abstrakt metod operate.
En lambda-uttryck användes för att implementera denna metod, vilket utför addition av två tal.
Resultatet av additionen skrevs ut.
Jag förstår att det kan vara utmanande att förstå vad som händer i denna kod just nu, men låt oss återgå till Stream API, där lambda-uttryck ofta används, och försöka förstå hur de används i praktiken.
Som du minns skapade vi tidigare en ström av strängar från en lista av strängar. Nu ska vi använda strömmens metoder för att göra varje sträng i denna ström versaler:
Main.java
12345678910111213package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); stream.map(e -> e.toUpperCase()).toList(); } }
I koden ovan använde vi ett lambda-uttryck och två metoder: map() och toList(). Om det är tydligt vad metoden toList() gör, så ändrar metoden map() varje element i streamen enligt det angivna lambda-uttrycket.
Låt oss titta närmare på hur lambda-uttrycket fungerar här:
Metoden map() tillämpar metoden toUpperCase() på varje element i streamen. Vi definierade elementet i denna stream som e och, med hjälp av lambda-uttrycket, instruerade vi programmet att tillämpa denna metod på varje element.
Men detta är inte slutet än eftersom vi har använt en intermediär operation. Det innebär att operationerna på streamen inte är avslutade än. För att slutföra arbetet med streamen behöver vi använda en terminal operation, som avslutar operationerna på streamen och returnerar ett specifikt värde. Till exempel kan du använda metoden toList(), och den modifierade streamen kommer att konverteras till en lista.
Till exempel:
Main.java
1234567891011121314package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.toUpperCase()).toList(); System.out.println(list); } }
Låt oss titta närmare på möjliga intermediära operationer i en stream.
Intermediära operationer
Metoden map() – du är redan bekant med denna metod; den utför operationer som anges av lambda-uttrycket på varje element i streamen.
Till exempel, låt oss använda metoden substring() på varje element i en ström av strängar:
Main.java
123456789101112131415package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }
filter()-metoden tar ett lambda-uttryck med ett villkor som används för att filtrera strömmen. Det vill säga, alla element som uppfyller villkoret kommer att finnas kvar i strömmen, och element som inte uppfyller villkoret kommer att tas bort från strömmen. Vi ändrar nu strömmen så att endast de element vars längd är större än 5 behålls:
Main.java
12345678910111213141516package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); stream = stream.filter(e -> e.length() > 5); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }
Med hjälp av metoden filter() tar vi bort strängen "with" från strömmen eftersom detta ord har färre än 5 tecken.
Det är även möjligt att använda intermediära operationer flera gånger i följd.
Till exempel kan vi förenkla ovanstående kod något:
Main.java
12345678910111213141516package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); List<String> list = strings.stream() .filter(e -> e.length() > 5) .map(e -> e.substring(1, 4)) .toList(); System.out.println("Modified list: " + list); } }
Vid kedjning av flera strömmetoder rekommenderas att placera varje metod på en ny rad för att avsevärt förbättra kodens läsbarhet.
Metoden flatMap() omvandlar varje element i en stream till en ny stream och kombinerar resultaten till en enda stream. Med andra ord kan vi med denna metod dela upp streamen i flera streams, som sedan slås samman till en stream. Till exempel, om du har en lista med strängar där varje sträng kan innehålla flera ord, såsom en lista med för- och efternamn. Och du behöver göra första bokstaven i varje av dessa ord versal:
Main.java
123456789101112131415161718192021222324package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }
I koden ovan skrev vi en separat privat metod som gör första bokstaven i ett ord versal och använde denna metod i map()-metoden tillsammans med ett lambda-uttryck.
Observera att vi med hjälp av metoden flatMap delar upp varje element i streamen till olika streams med hjälp av Arrays.stream(e.split(" ")). Eftersom metoden split() returnerar en array, behöver vi använda Arrays.stream() för att dela upp denna array till streams.
Därefter slås alla dessa streams samman till en stream, varefter vi använder metoden vi skrev. Nu har vi alla för- och efternamn på användare med första bokstaven versal.
Vet du vad som skulle vara intressant?
Om vi lägger dessa för- och efternamn i en HashMap, där nyckeln är efternamnet och värdet är förnamnet.
Låt oss implementera detta i koden:
Main.java
12345678910111213141516171819202122232425262728293031323334package com.example; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); Map<String, String> usersKeyValue = new HashMap<>(); for (int i = 0; i < list.size() - 1; i+=2) { String name = list.get(i); String surname = list.get(i + 1); usersKeyValue.put(surname, name); } System.out.println("Map with surnames as keys and names as values: " + usersKeyValue); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }
Med en enkel loop sparades förnamn och efternamn i variabler och därefter i mappen. Observera hur loopen fungerar. Variabeln i ökas med 2 i varje iteration eftersom vi behöver hoppa över efternamnet när det redan har registrerats.
- Metoden
distinct()tar bort dubbletter från streamen. Generellt kan detta vara användbart om unika element i streamen krävs eller om det behövs snabb eliminering av dubbletter från en lista. Detta kan enkelt uppnås med följande konstruktion:
list.stream().distinct().toList()
-
Metoden
sortedsorterar alla element i streamen i naturlig ordning, från det minsta till det största talet eller i alfabetisk ordning. Detta kan också vara användbart om en sorterad stream behövs eller om en lista snabbt behöver sorteras; -
Metoden
skip(n)hoppar över de förstanelementen i streamen. Detta kan vara användbart vid arbete med textfiler, där de första n raderna till exempel kan vara metadata eller en filbeskrivning. Det är även värt att nämna metodenlimit(n), som generellt begränsar antalet element i streamen. Även om en stream skapas med 1000 element och sedanlimit(200)används, kommer streamen endast att innehålla de första 200 elementen.
Main.java
123456789101112package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example = example.stream().skip(3).limit(5).toList(); System.out.println("List: " + example); } }
Detta är de viktigaste intermediära metoderna du behöver använda. Du kan utforska resten av metoderna genom att hänvisa till länk till den officiella Java-dokumentationen. Gå vidare till terminalmetoder.
Terminalmetoder
-
Den terminalmetod du redan är bekant med är
toList(). Den konverterar streamen till en lista och returnerar den. Det innebär att du direkt kan tilldela denna stream med metoder till en lista. Denna metod introducerades i Java 17 och ersätter den mer komplexa konstruktionencollect(Collectors.toList()); -
Metoden
collect()konverterar också streamen till en specifik datastruktur. Den använder, som parameter, en metod från gränssnittetCollectors. Detta gränssnitt har metoder såsomtoList(),toSet()ochtoCollection(). Till exempel:
Main.java
123456789101112131415package com.example; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Set<Integer> integerSet = example.stream().collect(Collectors.toSet()); System.out.println("List: " + example); System.out.println("Set: " + integerSet); } }
Metoden forEach() tar ett lambda-uttryck och utför en specifik åtgärd för varje element i strömmen.
Till exempel:
Main.java
1234567891011package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example.stream().forEach(e -> System.out.println(e + 1)); } }
Skillnaden mellan denna metod och map-metoden är att denna metod är terminal, och efter den kan du inte anropa andra metoder.
Detta är alla grundläggande metoder för att arbeta med streams. Det är ett komplext ämne, och du kanske inte förstår det direkt. Dock är det ett ämne som behärskas genom övning. I de kommande praktikavsnitten om streams kommer du att få många tillfällen att arbeta med dem, eftersom det är ett mycket bekvämt och praktiskt sätt att hantera listor och data-arrayer!
1. Vad är det primära syftet med Stream API i Java?
2. Vilken av följande är en terminaloperation i Stream API?
3. Vad gör operationen map i Stream API:t?
4. Hur skiljer sig operationen flatMap från map i Stream API:t?
5. Vad gör operationen filter i Stream API:t?
6. Vad är syftet med forEach-operationen i Stream API?
7. Vilken av följande är en intermediär operation i Stream API?
8. Hur används limit-operationen i Stream API?
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal
Fantastiskt!
Completion betyg förbättrat till 4
Stream-API i Java
Svep för att visa menyn
Det finns olika sätt att bearbeta data i Java – loopar, metoder och olika algoritmer. Men i Java 8 introducerades ett mycket kraftfullt verktyg – Stream API.
Enkelt uttryckt är Stream API ett sätt att arbeta snabbt och enkelt med en ström av information. I vårt fall representeras denna informationsström av samlingar. Stream API har vissa begrepp. Här är de viktigaste.
Huvudbegrepp
-
Stream: representerar en sekvens av dataelement som kan bearbetas;
-
Intermediära operationer: operationer som skapar en ny stream efter att de har utförts. Exempel:
filter,map,distinct,sorted; -
Terminala operationer: operationer som avslutar bearbetningen av streamen och returnerar ett resultat. Exempel:
collect,forEach,count,reduce; -
Parallella streams: möjliggör parallell bearbetning av data. Metoderna
parallel()ochparallelStream()används för att skapa parallella streams.
Nog med teori, låt oss börja koda!
En stream deklareras genom att använda en metod på den samling du vill omvandla till en stream:
Main.java
12List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream();
Med metoden stream() erhålls en stream av strängar. För att börja arbeta med streamen behöver vi dock förstå vad lambda-uttryck är, eftersom stream-metoder huvudsakligen använder dessa.
Lambda-uttryck
Lambda-uttryck introducerades i Java 8 och representerar en förenklad form av att skapa anonyma funktioner i Java. Vi har inte behandlat anonyma funktioner tidigare eftersom de inte varit särskilt nödvändiga, men nu kommer vi att bekanta oss med dem genom lambda-uttryck.
Syntax för lambda-uttryck:
Den allmänna syntaxen för lambda-uttryck i Java ser ut så här:
Example.java
123(parameters) -> expression // or (parameters) -> { statements; }
-
Parametrar: detta är en parameterlista som kan vara tom eller innehålla en eller flera parametrar;
-
Pil: representeras av symbolen
->, som separerar parametrarna från kroppen av lambda-uttrycket; -
Uttryck eller satser: detta är funktionens kropp, som innehåller ett uttryck eller ett block av satser.
Här är ett exempel på ett lambda-uttryck som representerar en enkel funktion som adderar två tal:
Example.java
12345678910// Traditional way MathOperation addition = new MathOperation() { @Override public int operate(int a, int b) { return a + b; } }; // Using a lambda expression MathOperation addition = (int a, int b) -> a + b;
Låt oss titta närmare på vad som faktiskt händer i koden ovan och hur vi använder lambda-uttryck:
Main.java
1234567891011121314package com.example; // Functional interface with a single abstract method interface MyMathOperation { int operate(int a, int b); } public class Main { public static void main(String[] args) { // Using a lambda expression to implement the interface MyMathOperation addition = (a, b) -> a + b; System.out.println("Sum: " + addition.operate(5, 3)); } }
I koden ovan:
En funktionell gränssnitt MyMathOperation skapades med en enda abstrakt metod operate.
En lambda-uttryck användes för att implementera denna metod, vilket utför addition av två tal.
Resultatet av additionen skrevs ut.
Jag förstår att det kan vara utmanande att förstå vad som händer i denna kod just nu, men låt oss återgå till Stream API, där lambda-uttryck ofta används, och försöka förstå hur de används i praktiken.
Som du minns skapade vi tidigare en ström av strängar från en lista av strängar. Nu ska vi använda strömmens metoder för att göra varje sträng i denna ström versaler:
Main.java
12345678910111213package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); stream.map(e -> e.toUpperCase()).toList(); } }
I koden ovan använde vi ett lambda-uttryck och två metoder: map() och toList(). Om det är tydligt vad metoden toList() gör, så ändrar metoden map() varje element i streamen enligt det angivna lambda-uttrycket.
Låt oss titta närmare på hur lambda-uttrycket fungerar här:
Metoden map() tillämpar metoden toUpperCase() på varje element i streamen. Vi definierade elementet i denna stream som e och, med hjälp av lambda-uttrycket, instruerade vi programmet att tillämpa denna metod på varje element.
Men detta är inte slutet än eftersom vi har använt en intermediär operation. Det innebär att operationerna på streamen inte är avslutade än. För att slutföra arbetet med streamen behöver vi använda en terminal operation, som avslutar operationerna på streamen och returnerar ett specifikt värde. Till exempel kan du använda metoden toList(), och den modifierade streamen kommer att konverteras till en lista.
Till exempel:
Main.java
1234567891011121314package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("a", "b", "c"); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.toUpperCase()).toList(); System.out.println(list); } }
Låt oss titta närmare på möjliga intermediära operationer i en stream.
Intermediära operationer
Metoden map() – du är redan bekant med denna metod; den utför operationer som anges av lambda-uttrycket på varje element i streamen.
Till exempel, låt oss använda metoden substring() på varje element i en ström av strängar:
Main.java
123456789101112131415package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }
filter()-metoden tar ett lambda-uttryck med ett villkor som används för att filtrera strömmen. Det vill säga, alla element som uppfyller villkoret kommer att finnas kvar i strömmen, och element som inte uppfyller villkoret kommer att tas bort från strömmen. Vi ändrar nu strömmen så att endast de element vars längd är större än 5 behålls:
Main.java
12345678910111213141516package com.example; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); Stream<String> stream = strings.stream(); stream = stream.filter(e -> e.length() > 5); List<String> list = stream.map(e -> e.substring(1, 4)).toList(); System.out.println("Modified list: " + list); } }
Med hjälp av metoden filter() tar vi bort strängen "with" från strömmen eftersom detta ord har färre än 5 tecken.
Det är även möjligt att använda intermediära operationer flera gånger i följd.
Till exempel kan vi förenkla ovanstående kod något:
Main.java
12345678910111213141516package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> strings = Arrays.asList("Unlock", "Infinity", "with", "Codefinity"); System.out.println("List of strings: " + strings); List<String> list = strings.stream() .filter(e -> e.length() > 5) .map(e -> e.substring(1, 4)) .toList(); System.out.println("Modified list: " + list); } }
Vid kedjning av flera strömmetoder rekommenderas att placera varje metod på en ny rad för att avsevärt förbättra kodens läsbarhet.
Metoden flatMap() omvandlar varje element i en stream till en ny stream och kombinerar resultaten till en enda stream. Med andra ord kan vi med denna metod dela upp streamen i flera streams, som sedan slås samman till en stream. Till exempel, om du har en lista med strängar där varje sträng kan innehålla flera ord, såsom en lista med för- och efternamn. Och du behöver göra första bokstaven i varje av dessa ord versal:
Main.java
123456789101112131415161718192021222324package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }
I koden ovan skrev vi en separat privat metod som gör första bokstaven i ett ord versal och använde denna metod i map()-metoden tillsammans med ett lambda-uttryck.
Observera att vi med hjälp av metoden flatMap delar upp varje element i streamen till olika streams med hjälp av Arrays.stream(e.split(" ")). Eftersom metoden split() returnerar en array, behöver vi använda Arrays.stream() för att dela upp denna array till streams.
Därefter slås alla dessa streams samman till en stream, varefter vi använder metoden vi skrev. Nu har vi alla för- och efternamn på användare med första bokstaven versal.
Vet du vad som skulle vara intressant?
Om vi lägger dessa för- och efternamn i en HashMap, där nyckeln är efternamnet och värdet är förnamnet.
Låt oss implementera detta i koden:
Main.java
12345678910111213141516171819202122232425262728293031323334package com.example; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class Main { public static void main(String[] args) { List<String> users = Arrays.asList("Ethan Johnson", "Olivia smith", "mason davis", "Ava taylor", "logan brown", "Emma Anderson", "jackson miller"); System.out.println("List of users: " + users); List<String> list = users.stream() .flatMap(e -> Arrays.stream(e.split(" "))) .map(e -> capitalizeFirstLetter(e)) .toList(); System.out.println("List with capitalized names and surnames: " + list); Map<String, String> usersKeyValue = new HashMap<>(); for (int i = 0; i < list.size() - 1; i+=2) { String name = list.get(i); String surname = list.get(i + 1); usersKeyValue.put(surname, name); } System.out.println("Map with surnames as keys and names as values: " + usersKeyValue); } private static String capitalizeFirstLetter(String word) { if (word == null || word.isEmpty()) { return word; } return Character.toUpperCase(word.charAt(0)) + word.substring(1); } }
Med en enkel loop sparades förnamn och efternamn i variabler och därefter i mappen. Observera hur loopen fungerar. Variabeln i ökas med 2 i varje iteration eftersom vi behöver hoppa över efternamnet när det redan har registrerats.
- Metoden
distinct()tar bort dubbletter från streamen. Generellt kan detta vara användbart om unika element i streamen krävs eller om det behövs snabb eliminering av dubbletter från en lista. Detta kan enkelt uppnås med följande konstruktion:
list.stream().distinct().toList()
-
Metoden
sortedsorterar alla element i streamen i naturlig ordning, från det minsta till det största talet eller i alfabetisk ordning. Detta kan också vara användbart om en sorterad stream behövs eller om en lista snabbt behöver sorteras; -
Metoden
skip(n)hoppar över de förstanelementen i streamen. Detta kan vara användbart vid arbete med textfiler, där de första n raderna till exempel kan vara metadata eller en filbeskrivning. Det är även värt att nämna metodenlimit(n), som generellt begränsar antalet element i streamen. Även om en stream skapas med 1000 element och sedanlimit(200)används, kommer streamen endast att innehålla de första 200 elementen.
Main.java
123456789101112package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example = example.stream().skip(3).limit(5).toList(); System.out.println("List: " + example); } }
Detta är de viktigaste intermediära metoderna du behöver använda. Du kan utforska resten av metoderna genom att hänvisa till länk till den officiella Java-dokumentationen. Gå vidare till terminalmetoder.
Terminalmetoder
-
Den terminalmetod du redan är bekant med är
toList(). Den konverterar streamen till en lista och returnerar den. Det innebär att du direkt kan tilldela denna stream med metoder till en lista. Denna metod introducerades i Java 17 och ersätter den mer komplexa konstruktionencollect(Collectors.toList()); -
Metoden
collect()konverterar också streamen till en specifik datastruktur. Den använder, som parameter, en metod från gränssnittetCollectors. Detta gränssnitt har metoder såsomtoList(),toSet()ochtoCollection(). Till exempel:
Main.java
123456789101112131415package com.example; import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); Set<Integer> integerSet = example.stream().collect(Collectors.toSet()); System.out.println("List: " + example); System.out.println("Set: " + integerSet); } }
Metoden forEach() tar ett lambda-uttryck och utför en specifik åtgärd för varje element i strömmen.
Till exempel:
Main.java
1234567891011package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); example.stream().forEach(e -> System.out.println(e + 1)); } }
Skillnaden mellan denna metod och map-metoden är att denna metod är terminal, och efter den kan du inte anropa andra metoder.
Detta är alla grundläggande metoder för att arbeta med streams. Det är ett komplext ämne, och du kanske inte förstår det direkt. Dock är det ett ämne som behärskas genom övning. I de kommande praktikavsnitten om streams kommer du att få många tillfällen att arbeta med dem, eftersom det är ett mycket bekvämt och praktiskt sätt att hantera listor och data-arrayer!
1. Vad är det primära syftet med Stream API i Java?
2. Vilken av följande är en terminaloperation i Stream API?
3. Vad gör operationen map i Stream API:t?
4. Hur skiljer sig operationen flatMap från map i Stream API:t?
5. Vad gör operationen filter i Stream API:t?
6. Vad är syftet med forEach-operationen i Stream API?
7. Vilken av följande är en intermediär operation i Stream API?
8. Hur används limit-operationen i Stream API?
Tack för dina kommentarer!