java爽看Stream

Java Stream MD笔记

一、Java Stream概念

Java Stream是Java 8引入的一种新的数据处理方式,提供了一种高效、便利的方法来处理集合数据。Stream流可以让开发人员以声明式的方式对数据进行操作,从而使代码更加简洁、易读。Stream本身不存储数据,而是通过管道传输数据,支持类似于SQL语句的操作,如过滤、映射、排序等。

二、Stream的特点

1. **不存储数据**:Stream操作是延迟执行的,只有在终端操作时才会触发实际的计算。
2. **不可变性**:Stream操作不会改变源对象,而是返回一个新的Stream。
3. **支持并行操作**:通过`parallelStream()`方法,可以将流转换为并行流,利用多核处理器提高处理性能。
4. **操作多样性**:提供了丰富的中间操作和终端操作,如`filter()`, `map()`, `sorted()`, `collect()`等。

三、Stream的创建

1. 通过集合创建

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

2. 通过数组创建

String[] array = {"ab", "abc", "abcd", "abcde", "abcdef"};
Stream<String> stream = Arrays.stream(array);

3. 使用Stream静态方法

Stream<String> stream = Stream.of("ab", "abc", "abcd", "abcde", "abcdef");
Stream<Integer> stream2 = Stream.iterate(0, x -> x + 3).limit(5);
Stream<Integer> stream3 = Stream.generate(() -> new Random().nextInt()).limit(3);

4. 通过IntStream、LongStream、DoubleStream接口

IntStream intStream = IntStream.of(1, 2, 3, 4, 5);
IntStream range = IntStream.range(1, 5);
IntStream rangeClosed = IntStream.rangeClosed(1, 5);

四、Stream的中间操作

1. 过滤(filter)

Stream<String> stringStream = Stream.of("111", "22", "33333", "4444", "5555555", "111");
Stream<String> filteredStream = stringStream.filter(o -> o.length() < 3);

2. 截取(limit)

Stream<String> limitedStream = stringStream.limit(2);

3. 跳过(skip)

Stream<String> skippedStream = stringStream.skip(2).limit(2);

4. 去重(distinct)

Stream<String> distinctStream = stringStream.distinct();

5. 排序(sorted)

Stream<String> sortedStream = stringStream.sorted((o1, o2) -> o2.length() - o1.length());

6. 映射(map)

Stream<Integer> mappedStream = stringStream.map(Integer::parseInt);

五、Stream的终端操作

1. 最小值(min)和最大值(max)

Optional<Integer> min = mappedStream.distinct().min(Integer::compare);
Optional<Integer> max = mappedStream.distinct().max(Integer::compare);

2. 计数(count)

long count = stringStream.count();

3. 归约(reduce)

int sum = mappedStream.distinct().reduce(0, Integer::sum);

4. 收集(collect)

List<String> collectedList = stringStream.collect(Collectors.toList());

六、Stream的并行操作

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int parallelSum = numbers.parallelStream().reduce(0, Integer::sum);

七、Stream与集合的比较

  • 简洁性:Stream流以声明式的方式操作数据,代码更加简洁、易读。
  • 延迟执行:Stream流的操作是延迟执行的,提高了效率

当然,很高兴能够继续扩展这篇关于Java Stream的MD笔记。下面,我将增加一些高级话题和实际应用场景,以便更全面地了解Java Stream的强大功能。

八、Stream的高级特性

1. 条件性操作(peek)

peek方法是一个中间操作,它接收一个Consumer函数式接口作为参数,对Stream中的每个元素执行操作,但不影响Stream本身。主要用于调试或日志记录等场景。

Stream<String> stream = Stream.of("a", "bb", "ccc", "dddd");
stream.peek(System.out::println).filter(s -> s.length() > 1).forEach(System.out::println);
// 输出:
// a
// bb
// ccc
// dddd
// bb
// ccc
// dddd

注意:虽然peek可以输出元素,但上面的例子中,原始流中的"a"也被输出了,因为它在过滤之前就被处理了。

2. 自定义收集器(Collectors)

Java Stream API提供了Collectors类,用于实现各种终端操作,如收集到列表、集合、映射等。但你也可以通过Collectors.collectingAndThen()Collectors.toMap()等方法的重载版本,以及自定义Collector来实现更复杂的收集逻辑。

Map<Boolean, List<String>> partition = stream.collect(Collectors.partitioningBy(s -> s.length() > 2));

// 自定义Collector示例
Collector<String, ?, String> joiningCollector = Collectors.collectingAndThen(
    Collectors.toList(),
    list -> String.join(",", list)
);
String joined = stream.collect(joiningCollector);

3. 扁平化流(flatMap)

当你有一个元素本身是流(或可以转换为流)的流时,flatMap方法非常有用。它将每个子流中的元素“扁平化”到主流中,从而得到一个包含所有子流元素的单一流。

List<List<String>> listOfLists = Arrays.asList(
    Arrays.asList("a", "b"),
    Arrays.asList("c", "d"),
    Arrays.asList("e")
);
Stream<String> flatStream = listOfLists.stream().flatMap(Collection::stream);
flatStream.forEach(System.out::println);
// 输出:
// a
// b
// c
// d
// e

九、Stream在实际应用中的案例

1. 文本处理

假设你有一个文件,包含多行文本,每行文本都是JSON格式的字符串。你可以使用Stream来读取文件,每行作为一个元素,然后解析JSON并处理数据。

Files.lines(Paths.get("data.txt"))
    .map(jsonLine -> new ObjectMapper().readValue(jsonLine, MyObject.class))
    .forEach(obj -> processObject(obj));

2. 复杂的数据转换

当你需要从一组复杂对象中提取特定信息,并将这些信息转换为另一种格式时,Stream API提供了强大的支持。

List<ComplexObject> complexObjects = ...;
List<String> result = complexObjects.stream()
    .map(obj -> obj.getNestedObject().getField())
    .filter(field -> !field.isEmpty())
    .collect(Collectors.toList());

3. 并发数据处理

Stream API支持并行流,可以利用多核处理器的优势来加速数据处理。但需要注意的是,并行流并不总是比顺序流更快,其性能取决于数据的特性和操作的复杂度。

IntStream.range(0, 1000).parallel()
    .map(i -> complexCalculation(i))
    .sum();

十、注意事项和最佳实践

  1. 性能考量:并行流不总是比顺序流快,特别是在数据量不大或操作不复杂时。此外,并行流可能会引入额外的线程开销和竞争条件。

  2. 中间操作与终端操作:确保你的Stream链以终端操作结束,否则Stream将不会执行任何操作。

  3. 状态管理:在Stream操作中避免使用可变状态,因为这可能会导致不可预测的结果。

  4. 错误处理:Stream API中的错误处理通常是通过异常来实现的。确保你的代码能够妥善处理可能抛出的异常。

  5. 可读性:虽然Stream API可以使代码更简洁,但过度使用或不恰当的使用可能会降低代码的可读性。保持代码的清晰和易于理解是很重要的。

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值