JDK8工具类引入新特性。java.util.stream.Stream

Stream不是集合本身,而是对集合 / 数组等数据源的 “计算管道”,支持链式调用、惰性求值,可高效实现过滤、映射、聚合等操作,尤其适合大数据量处理。

假设存在数据源:List<User> users = Arrays.asList( new User("张三", 25, "北京"), new User("李四", 30, "上海"), new User("王五", 25, "北京") );Usernameagecity字段及 getter)

filter(Predicate)过滤北京的用户:users.stream().filter(user -> "北京".equals(user.getCity())).collect(Collectors.toList());

等价于:使用明确的 Predicate 对象

import java.util.function.Predicate;
import java.util.stream.Collectors;

Predicate<User> isFromBeijing = user -> "北京".equals(user.getCity());

List<User> beijingUsers = users.stream()
        .filter(isFromBeijing)
        .collect(Collectors.toList());

map(Function)提取所有用户的姓名:

List<User> users = Arrays.asList(...);

// 方式1: Lambda 表达式
List<String> names1 = users.stream()
        .map(user -> user.getName())  // ← 这是Lambda表达式
        .collect(Collectors.toList());

// 方式2: 方法引用 (推荐)
List<String> names2 = users.stream()
        .map(User::getName)  // ← 这是方法引用[★★是Lambda表达式的语法糖★★]
        .collect(Collectors.toList());

// 方式3: 匿名类 (传统方式,不推荐)
List<String> names3 = users.stream()
        .map(new Function<User, String>() {
            @Override
            public String apply(User user) {
                return user.getName();
            }
        })  // ← 这是匿名类
        .collect(Collectors.toList());

sorted(Comparator)按年龄升序排序:

users.stream().sorted(Comparator.comparingInt(User::getAge)).collect(Collectors.toList());

Comparator.comparingInt()这是一个静态工厂方法,用于创建基于整数字段的比较器:

Comparator.comparingInt(User::getAge)
  • 接收一个 ToIntFunction(从对象提取int值的函数)
  • 返回一个 Comparator<User>,按提取的int值进行排序
  • 默认是升序排序

等价于:

Comparator<User> byAge = new Comparator<User>() {
    @Override
    public int compare(User u1, User u2) {
        return Integer.compare(u1.getAge(), u2.getAge());
    }
};

List<User> sortedByAge = users.stream()
        .sorted(byAge)
        .collect(Collectors.toList());

多重排序:

// 先按年龄升序,年龄相同再按姓名升序
List<User> multiSorted = users.stream()
        .sorted(Comparator.comparingInt(User::getAge)
                .thenComparing(User::getName))
        .collect(Collectors.toList());

collect(Collector)按城市分组(Map<String, List<User>>):

Map<String, List<User>> usersByCity = users.stream()
        .collect(Collectors.groupingBy(User::getCity));
  • Collectors.groupingBy(): 根据指定的分类函数进行分组
  • User::getCity: 分组依据,按城市字段分组
  • 返回 Map<String, List<User>>: 键是城市名,值是该城市的所有用户列表
// 按城市分组,然后统计每组的数量
Map<String, Long> countByCity = users.stream()
        .collect(Collectors.groupingBy(User::getCity, Collectors.counting()));

// 按城市分组,然后提取每组的姓名列表
Map<String, List<String>> namesByCity = users.stream()
        .collect(Collectors.groupingBy(User::getCity, 
                Collectors.mapping(User::getName, Collectors.toList())));

count()统计年龄≥28 的用户数:

long count = users.stream()
        .filter(u -> u.getAge() >= 28)
        .count();

findFirst()获取第一个满足条件的用户(返回Optional):

Optional<User> firstUser = users.stream()
        .filter(u -> u.getAge() == 25)
        .findFirst();
import java.util.Optional;

public class FindFirstExample {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(
            new User("张三", 25, "北京"),
            new User("李四", 30, "上海"),
            new User("王五", 25, "北京"),
            new User("赵六", 28, "上海")
        );

        // 查找第一个年龄为25的用户
        Optional<User> firstUser = users.stream()
                .filter(u -> u.getAge() == 25)
                .findFirst();

        // 处理Optional的几种方式
        // 方式1: ifPresent (如果存在则执行操作)
        firstUser.ifPresent(user -> 
            System.out.println("找到用户: " + user.getName()));

        // 方式2: orElse (如果不存在返回默认值)
        User result = firstUser.orElse(new User("默认用户", 0, "未知"));
        System.out.println("结果用户: " + result.getName());

        // 方式3: orElseGet (懒加载默认值)
        User result2 = firstUser.orElseGet(() -> new User("懒加载用户", 0, "未知"));

        // 懒加载默认值指的是:只有在真正需要的时候才创建或计算默认值,而不是预先创建好。这是一种性能优化策略,避免不必要的对象创建和计算开销。在大多数情况下,特别是当默认值的创建成本较高时,应该优先使用 orElseGet() 来获得更好的性能。只有在默认值非常简单且成本极低时,才使用 orElse()。
        
        // 方式4: orElseThrow (如果不存在抛出异常)
        try {
            User result3 = firstUser.orElseThrow(() -> 
                new RuntimeException("用户不存在"));
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }

        // 方式5: 直接获取值(不推荐,可能抛异常)
        if (firstUser.isPresent()) {
            User user = firstUser.get();
            System.out.println("直接获取: " + user.getName());
        }
    }
}

打印:

users.forEach(System.out::println);

并行 Stream 示例:

// 并行计算所有用户的年龄总和(自动分配多线程)
int totalAge = users.parallelStream()
                   .mapToInt(User::getAge)
                   .sum();
分类: Java-Backend 标签: Java

评论

暂无评论数据

暂无评论数据

目录