Java Stream是Java 8中添加的新特性,它提供了一种全新的、优雅的方式来操作数据集合。这种方式可以让我们避免使用迭代器等重复性代码,而是使用更加易于理解和维护的函数式编程的方式来处理数据。Java Stream能够对集合进行过滤、排序、映射等操作,同时还可以支持多线程处理。本文将介绍Java Stream的使用方法,并展示如何使用Java Stream来优雅地处理数据。
一、Stream的基本概念
Stream是一个用于处理集合的标准化操作的概念。其本质是对数据源的一系列操作封装成一条流水线,类似于一条流水线上的清洗、加工、包装等工作,最终生成一个处理完成的结果。Stream表示数据流,和集合使用类似,但在某些情况下,Stream更胜一筹。Stream只是一个声明式的概念,不会改变数据源的元素,产生的结果也仅限于终止操作。使用Stream,可以大大减少程序的复杂性和代码冗余。
1.1 Stream的初步创建方法
Stream可以有两种创建方式,一种是通过集合或数组的Stream()方法进行创建,一种是通过Stream.of()方法传入一系列元素进行创建。Stream可以看成是一个元素的集合,每次对元素集合的操作都会返回一个新的元素集合。下面是通过数组和集合创建Stream的示例:
public class StreamTest {
public static void main(String[] args) {
// 通过数组创建Stream
int[] nums = {1, 3, 5, 7, 9};
IntStream stream = Arrays.stream(nums);
System.out.println("通过数组创建Stream");
stream.forEach(System.out::println);
// 通过集合创建Stream
List
words = new ArrayList<>();
words.add("mina");
words.add("momo");
words.add("sana");
Stream
stream1 = words.stream();
System.out.println("通过集合创建Stream");
stream1.forEach(System.out::println);
}
}
1.2 Stream的中间操作方法
Stream提供了多种中间操作方法,这些方法可以看做是在Stream生成的元素集合上的一些处理操作,中间操作方法执行完毕后,仍可以执行后续的操作,这些方法不生成真正的处理结果,直到执行终止操作才会生成。下面是一些常见的中间操作方法:
filter方法
filter方法可以接收一个Predicate参数,用于对元素集合进行过滤操作,只有符合条件的元素才能进入下一步操作。下面的代码片段展示了使用filter方法过滤出大于3的数字:
// Filer示例
List
list = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).filter(num -> num > 3).collect(Collectors.toList());
System.out.println("Filter示例");
list.forEach(System.out::println); //输出4,5,6,7,8,9
map方法
map方法可以接收一个Function参数,用于对元素集合进行映射操作,返回一个新的元素集合。下面的代码片段展示了使用map方法将字符串转成大写形式:
// Map示例
List
list = Stream.of("hello", "world", "mina").map(String::toUpperCase).collect(Collectors.toList());
System.out.println("Map示例");
list.forEach(System.out::println); //输出HELLO,WORLD,MINA
flatMap方法
flatMap方法可以接收一个Function参数,用于将多个元素集合合并成一个新的元素集合。下面的代码片段展示了使用flatMap方法将多个集合合并成一个新的集合:
// FlatMap示例
List
list1 = Arrays.asList(1, 2, 3);
List
list2 = Arrays.asList(4, 5, 6);
List
list3 = Arrays.asList(7, 8, 9);
List
list = Stream.of(list1, list2, list3).flatMap(Collection::stream).collect(Collectors.toList());
System.out.println("FlatMap示例");
list.forEach(System.out::println); //输出1,2,3,4,5,6,7,8,9
distinct方法
distinct方法用于去重,对于某些数据处理场景来说十分有用。下面的代码片段展示了对元素集合进行去重操作的方法:
// Distinct示例
List
list = Stream.of(1, 2, 3, 2, 1, 5, 4, 3).distinct().collect(Collectors.toList());
System.out.println("Distinct示例");
list.forEach(System.out::println); //输出1,2,3,5,4
1.3 Stream的结束操作方法
结束操作方法是对元素集合进行终止处理的方法,这些方法执行后会生成真正的处理结果。Stream提供了多种结束操作方法,最常见的是forEach和collect方法。
forEach方法
forEach方法可以对元素集合进行遍历操作,并对每个元素执行指定的操作。下面的代码片段展示了使用forEach方法打印元素集合中的所有元素:
// ForEach示例
Stream.of("apple", "banana", "orange").forEach(System.out::println);
collect方法
collect方法可以将Stream的处理结果收集到一个集合中。下面的代码片段展示了使用collect方法将Stream处理结果收集到一个列表中:
// Collect示例
List
list = Stream.of("apple", "banana", "orange").collect(Collectors.toList());
System.out.println("Collect示例");
list.forEach(System.out::println); //输出apple,banana,orange
二、Stream的优雅操作数据
Stream的特点就在于它提供了一种更加简洁、易于理解和维护的方式操作数据。在实际使用中,Stream可以用于各种数据集合的操作,无论是数组、集合还是数据库操作,Stream都可以通过优雅的方式实现,从而使程序变得更加高效、简洁。
2.1 Stream在集合操作中的应用
Stream可以与集合操作结合使用,实现各种集合的处理操作,使集合的操作变得更加简单、高效。下面是一些在集合操作中使用Stream的常用方法示例:
filter方法实现集合过滤
集合过滤操作是Stream在实际应用中最常用的操作之一。可以使用filter方法实现简单的过滤操作。下面的代码展示了如何使用filter方法过滤集合中的元素:
public class StreamTest {
public static void main(String[] args) {
List
list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
// 过滤出大于3的元素
List
filteredList = list.stream().filter(num -> num > 3).collect(Collectors.toList());
System.out.println("Filter示例");
filteredList.forEach(System.out::println); //输出4,5,6
}
}
map方法实现集合转换
集合转换操作是Stream在实际应用中的另一种常见操作,可以使用map方法将集合中的元素转换为另一种类型的元素,达到转换集合类型的效果。下面的代码展示了如何使用map方法将集合中的元素整数转换成字符串形式:
public class StreamTest {
public static void main(String[] args) {
List
list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
// 将元素转换为字符串并收集为一个List
List
strList = list.stream().map(num -> num.toString()).collect(Collectors.toList());
System.out.println("Map示例");
strList.forEach(System.out::println); //输出1,2,3,4,5,6
}
}
reduce方法实现集合归约
集合归约操作是Stream中比较复杂的一种操作,可以使用reduce方法将集合中的元素归约成一个值。下面的代码展示了如何使用reduce方法将集合中的元素相加:
public class StreamTest {
public static void main(String[] args) {
List
list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
Optional<Integer> sum = list.stream().reduce((num1, num2) -> num1 + num2);
System.out.println("Reduce示例");
System.out.println(sum.get()); //输出21
}
}
2.2 Stream在数据库操作中的应用
应用程序在处理大型数据集时经常需要进行数据库操作。在Java中,我们通常使用JDBC来操作数据库。使用Stream可以更加优雅地处理数据库数据。下面是一个使用Stream进行数据库操作的示例:
// 数据库Student表有id,name,age三个字段
public class StreamTest {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC";
String name = "root";
String password = "root";
// 创建数据源
DataSource dataSource = null;
try {
dataSource = DruidDataSourceFactory.createDataSource(new Properties() {{
setProperty("driverClassName", "com.mysql.jdbc.Driver");
setProperty("url", url);
setProperty("username", name);
setProperty("password", password);
}});
} catch (Exception e) {
e.printStackTrace();
}
// 从数据库中查询结果并使用Stream对结果进行处理
try (Connection conn = dataSource.getConnection()) {
PreparedStatement prepStatement = conn.prepareStatement("SELECT * FROM Student");
ResultSet resultSet = prepStatement.executeQuery();
List<Student> students = new ArrayList<>();
while (resultSet.next()) {
Student student = new Student();
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setAge(resultSet.getInt("age"));
students.add(student);
}
// 使用Stream从查询结果中过滤出年龄大于18岁的学生
List<String> names = students.stream().filter(student -> student.getAge() > 18).map(Student::getName).collect(Collectors.toList());
System.out.println("JDBC + Stream示例");
names.forEach(System.out::println); //输出年龄大于18岁的学生姓名列表
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// Student类
public class Student {
private Integer id;
private String name;
private Integer age;
// TODO: Setter & Getter方法
}
三、总结
Stream是一种全新的、优雅的方式来操作数据集合,相比于传统的操作方式,Stream拥有更好的可读性、可维护性和性能。Stream可以用于处理各种类型的数据集合,包括数组、集合和数据库中的数据。在实际应用中,Stream可以提高代码的可读性、可维护性和代码的重用性,从而提高开发的效率。