Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lära Stream-API i Java | Avancerade Java-Funktioner och Tekniker
Quizzes & Challenges
Quizzes
Challenges
/
Java Datastrukturer

bookStream-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() och parallelStream() 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

Main.java

copy
12
List<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

Example.java

copy
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

Example.java

copy
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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
12345678910111213
package 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021222324
package 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

Main.java

copy
12345678910111213141516171819202122232425262728293031323334
package 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 sorted sorterar 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örsta n elementen 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 metoden limit(n), som generellt begränsar antalet element i streamen. Även om en stream skapas med 1000 element och sedan limit(200) används, kommer streamen endast att innehålla de första 200 elementen.

Main.java

Main.java

copy
123456789101112
package 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 konstruktionen collect(Collectors.toList());

  • Metoden collect() konverterar också streamen till en specifik datastruktur. Den använder, som parameter, en metod från gränssnittet Collectors. Detta gränssnitt har metoder såsom toList(), toSet() och toCollection(). Till exempel:

Main.java

Main.java

copy
123456789101112131415
package 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

Main.java

copy
1234567891011
package 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?

question mark

Vad är det primära syftet med Stream API i Java?

Select the correct answer

question mark

Vilken av följande är en terminaloperation i Stream API?

Select the correct answer

question mark

Vad gör operationen map i Stream API:t?

Select the correct answer

question mark

Hur skiljer sig operationen flatMap från map i Stream API:t?

Select the correct answer

question mark

Vad gör operationen filter i Stream API:t?

Select the correct answer

question mark

Vad är syftet med forEach-operationen i Stream API?

Select the correct answer

question mark

Vilken av följande är en intermediär operation i Stream API?

Select the correct answer

question mark

Hur används limit-operationen i Stream API?

Select the correct answer

Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 4. Kapitel 3

Fråga AI

expand

Fråga AI

ChatGPT

Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal

bookStream-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() och parallelStream() 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

Main.java

copy
12
List<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

Example.java

copy
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

Example.java

copy
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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
12345678910111213
package 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021222324
package 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

Main.java

copy
12345678910111213141516171819202122232425262728293031323334
package 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 sorted sorterar 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örsta n elementen 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 metoden limit(n), som generellt begränsar antalet element i streamen. Även om en stream skapas med 1000 element och sedan limit(200) används, kommer streamen endast att innehålla de första 200 elementen.

Main.java

Main.java

copy
123456789101112
package 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 konstruktionen collect(Collectors.toList());

  • Metoden collect() konverterar också streamen till en specifik datastruktur. Den använder, som parameter, en metod från gränssnittet Collectors. Detta gränssnitt har metoder såsom toList(), toSet() och toCollection(). Till exempel:

Main.java

Main.java

copy
123456789101112131415
package 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

Main.java

copy
1234567891011
package 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?

question mark

Vad är det primära syftet med Stream API i Java?

Select the correct answer

question mark

Vilken av följande är en terminaloperation i Stream API?

Select the correct answer

question mark

Vad gör operationen map i Stream API:t?

Select the correct answer

question mark

Hur skiljer sig operationen flatMap från map i Stream API:t?

Select the correct answer

question mark

Vad gör operationen filter i Stream API:t?

Select the correct answer

question mark

Vad är syftet med forEach-operationen i Stream API?

Select the correct answer

question mark

Vilken av följande är en intermediär operation i Stream API?

Select the correct answer

question mark

Hur används limit-operationen i Stream API?

Select the correct answer

Var allt tydligt?

Hur kan vi förbättra det?

Tack för dina kommentarer!

Avsnitt 4. Kapitel 3
some-alt