【Stream介绍】JAVA8中Stream常用方法总结与样例介绍

Java Stream 流完全指南

Stream 是 Java 8 引入的一种处理集合数据的强大抽象,它允许我们以声明式方式处理数据集合,而不是通过循环迭代。下面详细介绍 Stream 的使用方法、功能及实际应用场景。

一、Stream 基础概念

1.1 什么是 Stream

Stream 是一个支持顺序和并行聚合操作的元素序列。它不是数据结构,而是一种在数据集合上进行复杂操作的抽象视图。

1.2 Stream 操作分类

中间操作:返回新的 Stream,可以链接多个操作(延迟执行)

终端操作:触发流的计算,生成结果或副作用

二、创建 Stream

2.1 从集合创建

// 从 List 创建

List<String> list = Arrays.asList("a", "b", "c");

Stream<String> stream = list.stream();

// 从 Set 创建

Set<String> set = new HashSet<>(Arrays.asList("a", "b", "c"));

Stream<String> stream = set.stream();

// 从 Map 创建

Map<String, Integer> map = new HashMap<>();

map.put("a", 1);

map.put("b", 2);

Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();

扩展:

map.entrySet()是一种便捷遍历访问map中元素的方法,方法返回一个 Set,其中包含了 Map 中的所有键值对。每个键值对由 Map.Entry 表示。

2.2 从数组创建

String[] arr = {"a", "b", "c"};

Stream<String> stream = Arrays.stream(arr);

2.3 其他创建方式

// 使用 Stream.of

Stream<String> stream = Stream.of("a", "b", "c");

// 创建空流

Stream<String> emptyStream = Stream.empty();

// 创建无限流

Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2); // 偶数流

Stream<Double> randomStream = Stream.generate(Math::random);     // 随机数流

三、常用中间操作

3.1 filter - 过滤元素

// 功能:保留满足条件的元素

Stream<T> filter(Predicate<? super T> predicate)

使用场景:筛选满足特定条件的数据

// 示例:筛选成年用户

List<User> adults = userList.stream()

    .filter(user -> user.getAge() >= 18)

    .collect(Collectors.toList());

3.2 map - 元素映射转换

// 功能:将元素转换为其他形式

<R> Stream<R> map(Function<? super T, ? extends R> mapper)

使用场景:提取对象中的特定属性,或进行数据转换

// 示例:提取用户名列表

List<String> userNames = userList.stream()

    .map(User::getName)

    .collect(Collectors.toList());

3.3 flatMap - 扁平化映射

// 功能:将流中的每个元素映射为一个流,然后将所有流连接起来

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)

使用场景:处理嵌套集合,将多层集合扁平化为一层

// 示例:获取所有用户的所有标签

List<String> allTags = userList.stream()

    .flatMap(user -> user.getTags().stream())

    .distinct()

    .collect(Collectors.toList());

3.4 distinct - 去重

// 功能:去除重复元素

Stream<T> distinct()

使用场景:去除集合中的重复元素

// 示例:获取不重复的城市列表

List<String> uniqueCities = userList.stream()

    .map(User::getCity)

    .distinct()

    .collect(Collectors.toList());

3.5 sorted - 排序

// 功能:对流中的元素进行排序

Stream<T> sorted()

Stream<T> sorted(Comparator<? super T> comparator)

使用场景:对数据进行排序处理

// 示例:按年龄对用户排序

List<User> sortedUsers = userList.stream()

    .sorted(Comparator.comparing(User::getAge))

    .collect(Collectors.toList());

3.6 peek - 元素遍历操作

// 功能:对流中的元素执行操作,主要用于调试

Stream<T> peek(Consumer<? super T> action)

使用场景:调试流操作或执行不改变元素的操作

// 示例:在处理过程中记录日志

List<User> processedUsers = userList.stream()

    .peek(user -> log.info("Processing user: {}", user.getName()))

    .filter(user -> user.getAge() > 20)

    .collect(Collectors.toList());

3.7 limit - 限制元素数量

// 功能:限制流中元素的数量

Stream<T> limit(long maxSize)

使用场景:分页、限制结果集大小

// 示例:获取前5个用户

List<User> topFiveUsers = userList.stream()

    .limit(5)

    .collect(Collectors.toList());

3.8 skip - 跳过元素

// 功能:跳过前n个元素

Stream<T> skip(long n)

使用场景:分页查询

// 示例:分页查询(第2页,每页10条)

List<User> pageUsers = userList.stream()

    .skip(10)  // 跳过第1页

    .limit(10) // 获取10条

    .collect(Collectors.toList());

四、常用终端操作

4.1 collect - 收集结果

// 功能:将流中的元素收集到集合或其他容器中

<R, A> R collect(Collector<? super T, A, R> collector)

使用场景:将流转换为集合或其他数据结构

// 示例1:收集为List

List<User> userList = userStream.collect(Collectors.toList());

// 示例2:收集为Set

Set<String> uniqueNames = userStream

    .map(User::getName)

    .collect(Collectors.toSet());

// 示例3:收集为Map

Map<String, User> userMap = userStream

    .collect(Collectors.toMap(User::getId, user -> user));

4.2 forEach - 遍历执行

// 功能:对流中的每个元素执行操作

void forEach(Consumer<? super T> action)

使用场景:遍历元素,执行操作

// 示例:发送邮件给所有用户

userList.stream()

    .forEach(user -> emailService.sendEmail(user.getEmail(), "Hello", "Content"));

4.3 reduce - 归约

// 功能:将流中的元素组合起来,得到单个结果

Optional<T> reduce(BinaryOperator<T> accumulator)

T reduce(T identity, BinaryOperator<T> accumulator)

使用场景:求和、求最大值、连接字符串等

// 示例1:计算总和

int sum = numbers.stream()

    .reduce(0, Integer::sum);

// 示例2:连接字符串

String combined = strings.stream()

    .reduce("", (a, b) -> a + "," + b);

4.4 count - 计数

// 功能:计算流中的元素数量

long count()

使用场景:统计元素数量

// 示例:统计成年用户数量

long adultCount = userList.stream()

    .filter(user -> user.getAge() >= 18)

    .count();

4.5 anyMatch/allMatch/noneMatch - 匹配判断

// 功能:检查流中的元素是否满足条件

boolean anyMatch(Predicate<? super T> predicate)  // 任意一个元素满足条件

boolean allMatch(Predicate<? super T> predicate)  // 所有元素都满足条件

boolean noneMatch(Predicate<? super T> predicate) // 所有元素都不满足条件

使用场景:检查数据是否满足某些条件

// 示例1:检查是否有未成年用户

boolean hasMinors = userList.stream()

    .anyMatch(user -> user.getAge() < 18);

// 示例2:检查是否所有用户都已验证

boolean allVerified = userList.stream()

    .allMatch(User::isVerified);

4.6 findFirst/findAny - 查找元素

// 功能:返回流中的某个元素

Optional<T> findFirst() // 返回第一个元素

Optional<T> findAny()   // 返回任意一个元素(在并行流中更高效)

使用场景:查找满足条件的元素

// 示例:查找第一个管理员用户

Optional<User> firstAdmin = userList.stream()

    .filter(user -> "ADMIN".equals(user.getRole()))

    .findFirst();

4.7 min/max - 最小值/最大值

// 功能:根据比较器返回流中的最小值/最大值

Optional<T> min(Comparator<? super T> comparator)

Optional<T> max(Comparator<? super T> comparator)

使用场景:查找最小/最大值元素

// 示例1:查找年龄最大的用户

Optional<User> oldestUser = userList.stream()

    .max(Comparator.comparing(User::getAge));

// 示例2:查找最便宜的产品

Optional<Product> cheapestProduct = productList.stream()

    .min(Comparator.comparing(Product::getPrice));

五、实际应用场景示例

5.1 数据转换与清洗

// 将实体列表转换为DTO列表并过滤掉无效数据

List<UserDTO> validUserDtos = userEntities.stream()

    .filter(entity -> entity.getStatus().equals("ACTIVE"))

    .map(entity -> {

        UserDTO dto = new UserDTO();

        dto.setId(entity.getId());

        dto.setName(entity.getName());

        dto.setEmail(entity.getEmail());

        return dto;

    })

    .collect(Collectors.toList());

5.2 复杂业务统计

// 按部门统计员工平均工资

Map<String, Double> avgSalaryByDept = employees.stream()

    .collect(Collectors.groupingBy(

        Employee::getDepartment,

        Collectors.averagingDouble(Employee::getSalary)

    ));

// 统计各年龄段用户数量

Map<String, Long> userCountByAgeGroup = users.stream()

    .collect(Collectors.groupingBy(

        user -> {

            int age = user.getAge();

            if (age < 18) return "未成年";

            else if (age < 30) return "青年";

            else if (age < 50) return "中年";

            else return "老年";

        },

        Collectors.counting()

    ));

5.3 复杂数据过滤

// 查找满足多条件的订单

List<Order> filteredOrders = orders.stream()

    .filter(order -> order.getAmount().compareTo(new BigDecimal("1000")) > 0)

    .filter(order -> order.getStatus().equals("PAID"))

    .filter(order -> order.getCreateTime().isAfter(LocalDateTime.now().minusDays(30)))

    .collect(Collectors.toList());

5.4 集合操作

// 获取两个集合的交集

List<String> intersection = list1.stream()

    .filter(list2::contains)

    .collect(Collectors.toList());

// 获取两个集合的差集

List<String> difference = list1.stream()

    .filter(item -> !list2.contains(item))

    .collect(Collectors.toList());

5.5 数据分组与汇总

// 按状态分组订单并计算各组金额总和

Map<String, BigDecimal> orderTotalByStatus = orders.stream()

    .collect(Collectors.groupingBy(

        Order::getStatus,

        Collectors.reducing(

            BigDecimal.ZERO,

            Order::getAmount,

            BigDecimal::add

        )

    ));

// 按多个属性分组

Map<String, Map<String, List<Product>>> productsByTypeAndBrand = products.stream()

    .collect(Collectors.groupingBy(

        Product::getType,

        Collectors.groupingBy(Product::getBrand)

    ));

5.6 字符串处理

// 将句子中的单词提取、转小写、去重、排序

String sentence = "The quick brown fox jumps over the lazy dog";

List<String> uniqueWords = Arrays.stream(sentence.split("\\s+"))

    .map(String::toLowerCase)

    .distinct()

    .sorted()

    .collect(Collectors.toList());

5.7 并行处理大数据集

// 并行计算大数据集的统计信息

DoubleSummaryStatistics stats = largeNumberList.parallelStream()

    .mapToDouble(Double::valueOf)

    .summaryStatistics();

System.out.println("Count: " + stats.getCount());

System.out.println("Sum: " + stats.getSum());

System.out.println("Min: " + stats.getMin());

System.out.println("Max: " + stats.getMax());

System.out.println("Average: " + stats.getAverage());

5.8 文件处理

// 读取文件并统计单词频率

Map<String, Long> wordFrequency = Files.lines(Paths.get("book.txt"))

    .flatMap(line -> Arrays.stream(line.split("\\s+")))

    .map(word -> word.replaceAll("[^a-zA-Z]", "").toLowerCase())

    .filter(word -> !word.isEmpty())

    .collect(Collectors.groupingBy(

        Function.identity(),

        Collectors.counting()

    ));

六、高级应用技巧

6.1 Collectors 高级用法

// 分区(将数据分为满足条件和不满足条件两组)

Map<Boolean, List<User>> partitionedUsers = users.stream()

    .collect(Collectors.partitioningBy(user -> user.getAge() >= 18));

// 连接字符串

String joinedNames = users.stream()

    .map(User::getName)

    .collect(Collectors.joining(", ", "Names: [", "]"));

// 自定义收集器

Collector<Product, ?, BigDecimal> summingBigDecimal = 

    Collector.of(

        () -> new BigDecimal[]{BigDecimal.ZERO},

        (a, product) -> a[0] = a[0].add(product.getPrice()),

        (a, b) -> {

            a[0] = a[0].add(b[0]);

            return a;

        },

        a -> a[0]

    );

6.2 组合流操作

// 复杂过滤和转换的组合

List<TransactionDTO> result = transactions.stream()

    .filter(tx -> tx.getAmount().compareTo(BigDecimal.valueOf(100)) > 0)

    .filter(tx -> tx.getDate().isAfter(LocalDate.now().minusMonths(1)))

    .sorted(Comparator.comparing(Transaction::getDate).reversed())

    .limit(10)

    .map(transactionMapper::toDTO)

    .collect(Collectors.toList());

七、性能考虑

7.1 并行流性能优化

// 适合并行的场景:大数据量、元素独立计算、无状态操作

long count = veryLargeCollection.parallelStream()

    .filter(complexFilter)

    .count();

7.2 避免不必要的装箱/拆箱

// 使用基本类型流

double sum = IntStream.rangeClosed(1, 1000000)

    .filter(n -> n % 2 == 0)

    .average()

    .orElse(0);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值