学习目标:
- 掌握 Java Stream流的相关api
- 掌握 Java Stream流的基本实现
- 掌握 java Stream流的使用场景
- 代码已经整理上传到了gitee中,有需要的小伙伴可以取查看一下源码点个小心心喔
大家也可以帮我提交一点案例喔!!!!!
大家一起交流学习!
https://gitee.com/Aoyuan-210902/JAVAStreamDemo.git
点个赞嘛!!!!!!!!!!!!!!!!!!!!!!!!!
JAVA Stream流
概述
Java Stream API 是 Java 8 中引入的一个功能强大的新库,它提供了一种高效且声明式的处理数据集合的方法。通过使用 Streams,开发者可以写出简洁且易于理解的代码,用于对数据执行复杂的查询和聚合操作。
什么是Stream流,Stream流的特点是什么?
-
含义
在 Java 中,Stream 是对集合(Collection)对象功能的一个补充,它支持顺序和并行的聚集操作。Streams 不存储数据,它们只在需要时从源(如集合或数组)中获取数据。 -
主要特点
声明式:相比于传统的迭代方式,stream 提供了一种声明式的方法来表达数据处理任务。
可组合:stream 操作可以链接起来,形成一个大的流水线,这样可以表达复杂的数据处理策略(比如筛选,排序等)。
并行能力:Streams 可以透明地并行处理,利用多核架构而无需编写特定的多线程代码。
常见操作
Stream 操作分为中间操作和终端操作两种:
中间操作:如 filter、map、sorted 等,它们返回一个新的 Stream,可以连接多个中间操作。
终端操作:如 forEach、collect、reduce 等,它们输出结果或者产生副作用(例如输出到屏幕),并且关闭 Stream。
一些Stream的特性
- 函数式编程: 通过Stream流可以代替复繁琐难懂的for循环等代码,对数据进行操作。
- Stream流不会直接得出结果,而是在调用终端操作的时候,才会运行中间操作。
Optional类
在Java中,Optional是一个容器类,它可以包含也可以不包含非空值。Optional类主要用于防止NullPointerException异常的发生,它提供了一种更优雅的方法来处理可能为null的对象。使用Optional可以显式地要求调用者处理空值情况。
Optional提供了多种方法来检查、获取和转换包含的值:
isPresent():检查Optional是否有值。
get():获取Optional的值,如果Optional为空,则抛出NoSuchElementException。
orElse():如果Optional有值则返回该值,否则返回传递给orElse的参数。
ifPresent():如果值存在,执行给定的操作。 map()和flatMap():对Optional的值应用函数。
Optional常用于新的Java API中,如Stream的终端操作,返回一个Optional类型的结果
。
Stream流的操作
distinct
package distinctStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DistincrtStrream {
public static void main(String[] args) {
//distint主要是去除掉集合中重复的代码
List<Integer> list = Arrays.asList(1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6);
List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
collect.forEach(System.out::println);
}
}
运行实例
filter筛选操作
示例1
package filterStream;
import java.util.ArrayList;
import java.util.List;
public class FilterDemo01 {
//找到集合中元素大于5的数
public static void main(String[] args) {
List<Integer> demo01 = new ArrayList<>();
demo01.add(1);
demo01.add(5);
demo01.add(7);
demo01.add(8);
demo01.add(9);
System.out.println("没有进行筛选之前的数据");
demo01.forEach(System.out::println);
System.out.println("筛选之后的数据");
demo01.stream().filter(x -> x > 5).forEach(System.out::println);
}
}
示例2
package filterStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class FilterDemo02 {
public String username;
public String password;
public FilterDemo02() {
}
public FilterDemo02(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "FilterDemo02{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
public static void main(String[] args) {
FilterDemo02 user01 = new FilterDemo02("aoyuan","123");
FilterDemo02 user02 = new FilterDemo02("yuan","234");
FilterDemo02 user03 = new FilterDemo02("ao","345");
List<FilterDemo02> list = new ArrayList<>();
list.add(user01);
list.add(user02);
list.add(user03);
//查找username = aoyuan的
List<FilterDemo02> collect = list.stream().filter(n -> n.getUsername().equals("aoyuan")).collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("------------------------------------------------------------------------------");
//查找username =ao
List<FilterDemo02> collect01 = list.stream().filter(n -> n.getUsername().equals("ao")).collect(Collectors.toList());
collect01.forEach(System.out::println);
System.out.println("------------------------------------------------------------------------------");
List<FilterDemo02> collect02 = list.stream().filter(n -> n.getPassword() != "123").collect(Collectors.toList());
collect02.forEach(System.out::println);
}
}
运行示例
limit截取操作
示例1
package limitStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class LimitDemo01 {
public static void main(String[] args) {
//limit是截取第n个元素
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
Stream<Integer> limit1 = list.stream().limit(2);
Stream<Integer> limit2 = list.stream().limit(6);
System.out.println("----------------截取第2个---------------");
limit1.forEach(System.out::println);
System.out.println("-----------------截取6个---------------------");
limit2.forEach(System.out::println);
}
}
运行示例
示例2
package limitStream;
import java.util.stream.Stream;
public class LimitDemo02 {
public static void main(String[] args) {
//interage迭代器会一直进行下去,所以由inerate创建的流是无限流,需要limit方法截断
Stream<Integer> demo03 = Stream.iterate(0, n -> n+2).limit(6);
demo03.forEach(System.out::println);
System.out.println("limit起到了什么作用呢?起到了截断的作用");
Stream<Integer> demo04 = Stream.iterate(0,n -> n+2).limit(7);
demo04.forEach(System.out::println);
System.out.println("generate方法");
//generate方法
Stream<Double> generateStream = Stream.generate(Math::random).limit(5);
generateStream.forEach(System.out::println);
}
}
运行示例
map映射操作
User类
package mapStream;
public class User {
private String username;
private Integer id;
private String address;
public User() {
}
public User(String username, Integer id, String address) {
this.username = username;
this.id = id;
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", id=" + id +
", address='" + address + '\'' +
'}';
}
}
userdao类
package mapStream;
public class UserDao {
private String username;
private String address;
public UserDao() {
}
public UserDao(String username, String address) {
this.username = username;
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "UserDao{" +
"username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}
}
示例1
package mapStream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class FilterDemo01 {
public static void main(String[] args) {
List<User> userList= new ArrayList<>();
userList.add(new User("aoyuan",1,"baotou"));
userList.add(new User("aoyuan01",2,"bao"));
userList.add(new User("aoyuan02",3,"tou"));
//拿到用户集合中的数据并将用户名转化为大写
List<String> collect = userList.stream().map(x -> x.getUsername().toUpperCase()).collect(Collectors.toList());
collect.forEach(System.out::println);
//拿到user集合选择数据存储在新的userDao集合中
List<UserDao> collect1 = userList.stream().map(x -> {
UserDao userDao = new UserDao();
userDao.setUsername(x.getUsername());
userDao.setAddress(x.getAddress());
return userDao;
}).collect(Collectors.toList());
collect1.forEach(System.out::println);
}
}
运行示例
示例2
package mapStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class FilterDmeo02 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> collect = list.stream().map(x -> x + 3).collect(Collectors.toList());
collect.forEach(System.out::println);
}
}
运行示例
取max和min的相关操作
示例1
package maxStream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class Demo {
public static void main(String[] args) {
//自定义排序
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//从大到小排序
Optional<Integer> max = list.stream().max((o1, o2) -> o1 - o2);
System.out.println("最大值为+"+ max.get());
}
}
运行示例
示例2
package maxStream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Demo01 {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
Optional<Integer> max = list.stream().max(Integer::compareTo);
System.out.println("最大值为+:"+ max);
}
}
运行示例
示例3
package maxStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class Demo02 {
public static void main(String[] args) {
List<String> strings = Arrays.asList("aoyuan", "aoyuanao", "aoyuanaoyuan");
Optional<String> max = strings.stream().max(Comparator.comparing(String::length));
System.out.println("最长的字符串为" + max);
}
}
运行示例
示例3
package minStream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamMinExample01 {
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
int getAge() {
return age;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 22),
new Person("Bob", 20),
new Person("Charlie", 30),
new Person("David", 25)
);
Optional<Person> youngest = people.stream().min((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()));
youngest.ifPresent(person -> System.out.println("The youngest person is " + person));
}
}
运行示例
示例4
package minStream;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class StreamMinExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, -1, 6, 7);
// Using Stream.min() to find the minimum value in the list
Optional<Integer> minNumber = numbers.stream()
.min(Integer::compare);
// Checking and displaying the minimum number
if (minNumber.isPresent()) {
System.out.println("The minimum number is " + minNumber.get());
} else {
System.out.println("List is empty.");
}
}
}
运行示例
reduce归约
package reduce;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class ReduceStreamDemo {
public static void main(String[] args) {
List<Integer> demo = new ArrayList<>();
demo.add(2);
demo.add(4);
demo.add(1);
demo.add(5);
//x+y的和
Optional<Integer> reduce = demo.stream().reduce((x, y) -> x + y);
System.out.println(reduce.get());
//求最大值
Optional<Integer> reduce1 = demo.stream().reduce((x, y) -> x > y ? x : y);
System.out.println(reduce1.get());
}
}
运行示例
排序
示例1
package sortStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample {
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
String getName() {
return name;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 22),
new Person("Charlie", 30),
new Person("David", 25),
new Person("Bob", 20)
);
List<Person> sortedPeople = people.stream()
.sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
.collect(Collectors.toList());
sortedPeople.forEach(System.out::println);
}
}
运行示例
示例2
package sortStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class StreamSortExample02 {
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name + ": " + age;
}
}
public static void main(String[] args) {
List<Person> people = Arrays.asList(
new Person("Alice", 22),
new Person("Charlie", 30),
new Person("David", 25),
new Person("Bob", 20)
);
// Sorting people by age using Stream
List<Person> sortedByAge = people.stream()
//自然排序
.sorted((p1, p2) -> Integer.compare(p1.getAge(), p2.getAge()))
.collect(Collectors.toList());
// Displaying the sorted list
sortedByAge.forEach(System.out::println);
System.out.println("------------------自定义排序--------------");
//先根据年龄再根据姓名排序
List<Person> collect = people.stream().sorted((p1, p2) -> {
if (p1.getAge() == p2.getAge()) {
return p1.getName().compareTo(p2.getName());
} else {
return p2.getAge() - p1.getAge();
}
}).collect(Collectors.toList());
collect.forEach(System.out::println);
}
}
运行示例
总结
作用场景
Java Stream API 是用于处理集合和数据库的理想选择,它能够执行如排序、过滤或映射数据等聚合操作。Stream 支持并行处理,使得它能够有效地处理大型数据集。此外,Stream 在处理数据序列时能增强代码的可读性和减少样板代码,使编程更加表达和简洁。它在 Java 中的函数式编程模式中尤为有价值,帮助以声明方式操作集合。
优势和不足
优势
- 提高代码可读性和简洁性:通过流式表达式,可以用更少的代码完成复杂的集合处理,使代码更易于理解和维护。
- 支持并行处理:Stream API 设计支持并行执行,可以很容易地对数据进行并行处理,提高处理效率,尤其适用于处理大数据量。
- 函数式编程:支持函数式编程风格,有助于减少副作用,使程序更加稳定。
不足
- 性能开销:相对于传统的 for-loop,Stream 操作可能引入更多的性能开销,尤其是在小数据量或高性能场景中。
- 学习曲线:对于初学者,Stream API 的一些操作和概念可能比较难以理解,需要一定的学习投入。
- 调试困难:由于 Stream 操作的链式结构,调试可能比较复杂,特别是在流水线操作中定位问题可能比较困难。