Java中Stream?API的使用示例詳解
Java 在 Java 8 中提供了一個(gè)新的附加包,稱為 java.util.stream。該包由類、接口和枚舉組成,允許對(duì)元素進(jìn)行函數(shù)式操作。 您可以通過在程序中導(dǎo)入 java.util.stream包來使用流。
Stream提供以下功能
Stream不存儲(chǔ)元素。它只是通過計(jì)算操作的管道傳送來自數(shù)據(jù)結(jié)構(gòu)、數(shù)組或 I/O 通道等源的元素。
Stream本質(zhì)上是函數(shù)式的,對(duì)流執(zhí)行的操作不會(huì)修改其源。例如,過濾從集合獲取的 Stream 會(huì)生成一個(gè)沒有過濾元素的新 Stream,而不是從源集合中刪除元素。
Stream是惰性的,僅在需要時(shí)才計(jì)算代碼,在流的生命周期中,流的元素僅被訪問一次。
與迭代器一樣,必須生成新流才能重新訪問源中的相同元素。
您可以使用 Stream 來 過濾、收集、打印以及 從一種數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為其他數(shù)據(jù)結(jié)構(gòu)等。

Stream API 示例
1. 創(chuàng)建一個(gè)空的Stream
在創(chuàng)建空流時(shí),應(yīng)使用 empty() 方法:
Stream<String> stream = Stream.empty(); stream.forEach(System.out::println);
通常情況下,在創(chuàng)建時(shí)會(huì)使用 empty() 方法,以避免在沒有元素的流中返回 null:
public Stream<String> streamOf(List<String> list) {
return list == null || list.isEmpty() ? Stream.empty() : list.stream();
}
2.從集合中創(chuàng)建流
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
public class StreamCreationExamples {
public static void main(String[] args) throws IOException {
Collection<String> collection = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
Stream<String> stream2 = collection.stream();
stream2.forEach(System.out::println);
List<String> list = Arrays.asList("JAVA", "J2EE", "Spring", "Hibernate");
Stream<String> stream3 = list.stream();
stream3.forEach(System.out::println);
Set<String> set = new HashSet<>(list);
Stream<String> stream4 = set.stream();
stream4.forEach(System.out::println);
}
}
輸出
JAVA
J2EE
Spring
Hibernate
JAVA
J2EE
Spring
Hibernate
JAVA
Hibernate
J2EE
Spring
3. 從數(shù)組中創(chuàng)建流對(duì)象
數(shù)組可以是流的源,也可以從現(xiàn)有數(shù)組或數(shù)組的一部分創(chuàng)建數(shù)組:
import java.util.Arrays;
import java.util.stream.Stream;
public class StreamCreationExample {
public static void main(String[] args) {
// 使用Arrays.stream()創(chuàng)建流
int[] numbers = {1, 2, 3, 4, 5};
Stream<Integer> stream1 = Arrays.stream(numbers);
System.out.println("Using Arrays.stream():");
stream1.forEach(System.out::println);
// 使用Stream.of()創(chuàng)建流
String[] names = {"Alice", "Bob", "Charlie"};
Stream<String> stream2 = Stream.of(names);
System.out.println("Using Stream.of():");
stream2.forEach(System.out::println);
// 使用Stream.builder()創(chuàng)建流
String[] colors = {"Red", "Green", "Blue"};
Stream.Builder<String> builder = Stream.builder();
for (String color : colors) {
builder.add(color);
}
Stream<String> stream3 = builder.build();
System.out.println("Using Stream.builder():");
stream3.forEach(System.out::println);
}
}
輸出
Using Arrays.stream():
1
2
3
4
5
Using Stream.of():
Alice
Bob
Charlie
Using Stream.builder():
Red
Green
Blue
4. 使用Stream過濾一個(gè)集合示例
在下面的示例中,我們不使用流過濾數(shù)據(jù),看看代碼是什么樣的,同時(shí)我們?cè)诮o出一個(gè)使用stream過濾的示例,對(duì)比一下
不使用Stream過濾一個(gè)集合示例
import java.util.ArrayList;
import java.util.List;
public class FilterWithoutStreamExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.add(40);
numbers.add(50);
List<Integer> filteredNumbers = new ArrayList<>();
for (Integer number : numbers) {
if (number > 30) {
filteredNumbers.add(number);
}
}
System.out.println("Filtered numbers (without Stream):");
for (Integer number : filteredNumbers) {
System.out.println(number);
}
}
}
輸出:
Filtered numbers (without Stream):
40
50
使用 Stream 過濾集合示例:
import java.util.ArrayList;
import java.util.List;
public class FilterWithStreamExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.add(40);
numbers.add(50);
List<Integer> filteredNumbers = numbers.stream()
.filter(number -> number > 30)
.toList();
System.out.println("Filtered numbers (with Stream):");
filteredNumbers.forEach(System.out::println);
}
}
輸出:
Filtered numbers (with Stream):
40
50
前后我們對(duì)比一下,可以看到,使用 Stream 進(jìn)行集合過濾可以更加簡潔和直觀,減少了手動(dòng)迭代和添加元素的步驟。它提供了一種聲明式的編程風(fēng)格,使代碼更易讀、可維護(hù)和可擴(kuò)展。
5. 使用Stream過濾和遍歷集合
在下面的示例中,我們使用 filter() 方法進(jìn)行過濾,使用 forEach() 方法對(duì)數(shù)據(jù)流進(jìn)行迭代:
import java.util.ArrayList;
import java.util.List;
public class FilterAndIterateWithStreamExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
names.add("David");
names.add("Eve");
System.out.println("Filtered names starting with 'A':");
names.stream()
.filter(name -> name.startsWith("A"))
.forEach(System.out::println);
}
}
輸出
Filtered names starting with 'A':
Alice
在上述示例中,我們有一個(gè)字符串列表 names,其中包含了一些名字。
我們使用 Stream 進(jìn)行過濾和迭代操作以查找以字母 "A" 開頭的名字。
6.使用Collectors方法求和
我們還可以使用Collectors計(jì)算數(shù)值之和。
在下面的示例中,我們使用Collectors類及其指定方法計(jì)算所有產(chǎn)品價(jià)格的總和。
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SumByUsingCollectorsMethods {
public static void main(String[] args) {
List < Product > productsList = new ArrayList < Product > ();
productsList.add(new Product(1, "HP Laptop", 25000f));
productsList.add(new Product(2, "Dell Laptop", 30000f));
productsList.add(new Product(3, "Lenevo Laptop", 28000f));
productsList.add(new Product(4, "Sony Laptop", 28000f));
productsList.add(new Product(5, "Apple Laptop", 90000f));
double totalPrice3 = productsList.stream()
.collect(Collectors.summingDouble(product -> product.getPrice()));
System.out.println(totalPrice3);
}
}
輸出
201000.0
7. 使用Stream查找年齡最大和最小的學(xué)生
假設(shè)有一個(gè) Student 類具有 name 和 age 屬性。我們可以使用 Stream 來查找學(xué)生集合中年齡的最大和最小值,并打印出相應(yīng)的學(xué)生信息。以下是一個(gè)示例:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class StudentStreamExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(new Student("Charlie", 19));
students.add(new Student("David", 21));
// 查找年齡最大的學(xué)生
Optional<Student> maxAgeStudent = students.stream()
.max(Comparator.comparingInt(Student::getAge));
// 查找年齡最小的學(xué)生
Optional<Student> minAgeStudent = students.stream()
.min(Comparator.comparingInt(Student::getAge));
// 打印最大和最小年齡的學(xué)生信息
System.out.println("Student with maximum age:");
maxAgeStudent.ifPresent(System.out::println);
System.out.println("Student with minimum age:");
minAgeStudent.ifPresent(System.out::println);
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
輸出:
Student with maximum age:
Student{name='Bob', age=22}
Student with minimum age:
Student{name='Charlie', age=19}
8. 使用Stream轉(zhuǎn)換List為Map
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class StudentStreamToMapExample {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 20));
students.add(new Student("Bob", 22));
students.add(new Student("Charlie", 19));
students.add(new Student("David", 21));
// 將學(xué)生列表轉(zhuǎn)換為 Map,以姓名為鍵,學(xué)生對(duì)象為值
Map<String, Student> studentMap = students.stream()
.collect(Collectors.toMap(Student::getName, student -> student));
// 打印學(xué)生 Map
for (Map.Entry<String, Student> entry : studentMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
輸出
David: Student{name='David', age=21}
Bob: Student{name='Bob', age=22}
Charlie: Student{name='Charlie', age=19}
Alice: Student{name='Alice', age=20}
在上面示例中,我們使用Collectors.toMap() 方法將學(xué)生列表轉(zhuǎn)換為 Map。我們指定了鍵提取器 Student::getName,將學(xué)生的姓名作為鍵。對(duì)于值提取器,我們使用了一個(gè)匿名函數(shù) student -> student,它返回學(xué)生對(duì)象本身作為值。
9. 使用Stream把List對(duì)象轉(zhuǎn)換為另一個(gè)List對(duì)象
假設(shè)我們有一個(gè) Person 類,其中包含姓名和年齡屬性。我們可以使用 Stream 來將一個(gè) List 對(duì)象轉(zhuǎn)換為另一個(gè) List 對(duì)象,其中只包含人員的姓名。以下是一個(gè)示例:
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ListTransformationExample {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person("Alice", 20));
persons.add(new Person("Bob", 22));
persons.add(new Person("Charlie", 19));
// 將 Person 列表轉(zhuǎn)換為只包含姓名的 String 列表
List<String> names = persons.stream()
.map(Person::getName)
.collect(Collectors.toList());
// 打印轉(zhuǎn)換后的姓名列表
System.out.println(names);
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
輸出:
[Alice, Bob, Charlie]
在上述示例中,我們有一個(gè) Person 類,其中包含姓名和年齡屬性。我們創(chuàng)建了一個(gè) persons 列表,并添加了幾個(gè) Person 對(duì)象。
使用Stream,我們通過調(diào)用 map() 方法并傳入一個(gè)方法引用 Person::getName,最后,我們使用 collect()方法和 Collectors.toList() 將轉(zhuǎn)換后的姓名收集到一個(gè)新的列表中。
API
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
以上就是Java中Stream API的使用示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java Stream API的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決MyEclipse中的Building workspace問題的三個(gè)方法
這篇文章主要介紹了解決MyEclipse中的Building workspace問題的三個(gè)方法,需要的朋友可以參考下2015-11-11
將一個(gè)數(shù)組按照固定大小進(jìn)行拆分成數(shù)組的方法
下面小編就為大家?guī)硪黄獙⒁粋€(gè)數(shù)組按照固定大小進(jìn)行拆分成數(shù)組的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11
application.yaml與bootstrap.yaml的使用
這篇文章主要介紹了application.yaml與bootstrap.yaml的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Java多線程實(shí)戰(zhàn)之交叉打印的兩種方法
今天小編就為大家分享一篇關(guān)于Java多線程實(shí)戰(zhàn)之交叉打印的兩種方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-02-02
flowable動(dòng)態(tài)創(chuàng)建多級(jí)流程模板實(shí)現(xiàn)demo
這篇文章主要為大家介紹了flowable動(dòng)態(tài)創(chuàng)建多級(jí)流程模板實(shí)現(xiàn)demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Spring中的@PostConstruct注解使用方法解析
這篇文章主要介紹了Spring中的@PostConstruct注解使用方法解析,@PostConstruct注解是用來處理在@Autowired注入屬性后init()方法之前,對(duì)一些零散的屬性進(jìn)行賦值的注解,需要的朋友可以參考下2023-11-11

