Java Stream流处理示例小结

Stream API是Java 8引入的函数式编程特性,提供了一种高效处理集合数据的方式。以下是Stream流处理的常用操作示例。

图片[1]_Java Stream流处理示例小结_知途无界

一、基础操作

1. 创建Stream

// 从集合创建
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream1 = list.stream();

// 从数组创建
String[] array = {"a", "b", "c"};
Stream<String> stream2 = Arrays.stream(array);

// 直接创建
Stream<String> stream3 = Stream.of("a", "b", "c");

// 创建无限流
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);

2. 中间操作

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 过滤
Stream<String> filtered = names.stream()
    .filter(name -> name.length() > 4);

// 映射
Stream<Integer> nameLengths = names.stream()
    .map(String::length);

// 去重
Stream<String> distinct = names.stream()
    .distinct();

// 排序
Stream<String> sorted = names.stream()
    .sorted();

// 限制数量
Stream<String> limited = names.stream()
    .limit(2);

// 跳过元素
Stream<String> skipped = names.stream()
    .skip(1);

3. 终端操作

// 遍历
names.stream().forEach(System.out::println);

// 收集为List
List<String> collectedList = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

// 收集为Set
Set<String> collectedSet = names.stream()
    .collect(Collectors.toSet());

// 连接字符串
String joined = names.stream()
    .collect(Collectors.joining(", "));

// 计数
long count = names.stream().count();

// 匹配检查
boolean anyMatch = names.stream()
    .anyMatch(name -> name.startsWith("A"));
boolean allMatch = names.stream()
    .allMatch(name -> name.length() > 3);
boolean noneMatch = names.stream()
    .noneMatch(name -> name.length() > 10);

// 查找元素
Optional<String> first = names.stream().findFirst();
Optional<String> any = names.stream().findAny();

// 归约操作
Optional<String> longestName = names.stream()
    .reduce((name1, name2) -> 
        name1.length() > name2.length() ? name1 : name2);

二、高级操作

1. 数值流处理

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// 转换为IntStream
IntStream intStream = numbers.stream()
    .mapToInt(Integer::intValue);

// 求和
int sum = intStream.sum();

// 平均值
OptionalDouble avg = numbers.stream()
    .mapToInt(Integer::intValue)
    .average();

// 最大值
OptionalInt max = numbers.stream()
    .mapToInt(Integer::intValue)
    .max();

// 数值范围
IntStream range = IntStream.range(1, 5); // 1,2,3,4
IntStream rangeClosed = IntStream.rangeClosed(1, 5); // 1,2,3,4,5

2. 分组和分区

class Person {
    String name;
    int age;
    String city;
    // 构造方法、getter/setter省略
}

List<Person> people = Arrays.asList(
    new Person("Alice", 23, "New York"),
    new Person("Bob", 30, "New York"),
    new Person("Charlie", 28, "London"),
    new Person("David", 30, "London")
);

// 按城市分组
Map<String, List<Person>> byCity = people.stream()
    .collect(Collectors.groupingBy(Person::getCity));

// 按年龄分组并统计人数
Map<Integer, Long> countByAge = people.stream()
    .collect(Collectors.groupingBy(
        Person::getAge, 
        Collectors.counting()
    ));

// 分区(按条件分为true/false两组)
Map<Boolean, List<Person>> partitioned = people.stream()
    .collect(Collectors.partitioningBy(
        p -> p.getAge() > 25
    ));

// 多级分组
Map<String, Map<Integer, List<Person>>> byCityAndAge = people.stream()
    .collect(Collectors.groupingBy(
        Person::getCity,
        Collectors.groupingBy(Person::getAge)
    ));

3. 并行流处理

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

// 创建并行流
Stream<String> parallelStream = names.parallelStream();

// 并行处理示例
List<String> upperCaseNames = names.parallelStream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// 注意:并行流不保证顺序
List<String> unordered = names.parallelStream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// 保持顺序的并行处理
List<String> ordered = names.parallelStream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

三、实用示例

1. 文件处理

// 读取文件行
try (Stream<String> lines = Files.lines(Paths.get("data.txt"))) {
    List<String> filteredLines = lines
        .filter(line -> line.contains("error"))
        .collect(Collectors.toList());
} catch (IOException e) {
    e.printStackTrace();
}

// 遍历目录
try (Stream<Path> paths = Files.walk(Paths.get("/path/to/dir"))) {
    List<Path> javaFiles = paths
        .filter(Files::isRegularFile)
        .filter(p -> p.toString().endsWith(".java"))
        .collect(Collectors.toList());
} catch (IOException e) {
    e.printStackTrace();
}

2. 集合转换

// List转Map
Map<String, Integer> nameToLength = names.stream()
    .collect(Collectors.toMap(
        Function.identity(), // key
        String::length       // value
    ));

// 处理重复key
Map<String, Person> personByName = people.stream()
    .collect(Collectors.toMap(
        Person::getName,
        Function.identity(),
        (existing, replacement) -> existing // 解决key冲突
    ));

3. 复杂对象处理

// 获取所有城市列表
List<String> cities = people.stream()
    .map(Person::getCity)
    .distinct()
    .collect(Collectors.toList());

// 统计每个城市的平均年龄
Map<String, Double> avgAgeByCity = people.stream()
    .collect(Collectors.groupingBy(
        Person::getCity,
        Collectors.averagingInt(Person::getAge)
    ));

// 获取年龄最大的三个人
List<Person> top3Oldest = people.stream()
    .sorted(Comparator.comparingInt(Person::getAge).reversed())
    .limit(3)
    .collect(Collectors.toList());

四、性能注意事项

  1. 避免在流中执行耗时操作:流操作应保持简单高效
  2. 合理使用并行流:数据量大且处理复杂时使用
  3. 避免重复使用流:流一旦被消费就不能再次使用
  4. 优先使用方法引用:比lambda表达式更简洁高效
  5. 注意自动装箱:数值操作优先使用原始类型流(IntStream等)

五、常见问题解决方案

1. 处理空集合

List<String> names = getNames(); // 可能返回null
List<String> nonNullNames = Optional.ofNullable(names)
    .orElse(Collections.emptyList())
    .stream()
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

2. 多层集合扁平化

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

List<String> flatList = nestedList.stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList());

3. 自定义收集器

// 收集为不可变列表
List<String> immutableList = names.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.toList(),
        Collections::unmodifiableList
    ));

// 自定义统计收集器
IntSummaryStatistics stats = people.stream()
    .collect(Collectors.summarizingInt(Person::getAge));

Stream API极大地简化了集合操作代码,使数据处理更加直观和高效。掌握这些常用模式可以显著提高Java开发效率。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞6 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容