Java8新特性之Stream(一)

什么是Stream

Java 8引入了一个新的概念 - Stream(流),它是一种处理集合数据的新方式,具有简洁、可读性强、并行处理等优点。

Stream 是一个来自数据源的元素队列并支持聚合操作,它可以将多个操作组合起来,以管道的方式处理集合。在使用 Stream 时,首先需要指定一个数据源,比如一个 List、Set 或者数组等。然后可以对这个数据源执行一系列操作,这些操作分为两种类型:

- Intermediate:中间操作,会返回一个 Stream 对象,并且可以对该 Stream 进行下一步的操作。常用的中间操作有 filter、map、sorted 等。
- Terminal:终端操作,会返回一个非 Stream 的结果,常用的终端操作有 forEach、reduce、collect 等。

Stream 的使用流程大致如下:

1. 创建一个 Stream
2. 通过一系列的中间操作对 Stream 进行操作(过滤、排序、转换等)
3. 执行一个终端操作获取结果

上代码

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
                .filter(n -> n % 2 == 0)
                .mapToInt(Integer::intValue)
                .sum();
System.out.println(sum); // 输出 6

这段代码创建了一个包含 1 到 5 的整数列表,然后通过 stream() 方法将其转换成一个 Stream。接着使用 filter 方法过滤出偶数,然后使用 mapToInt 方法将 Integer 类型转换成 int 类型,最后使用 sum 方法计算所有元素的和并输出结果。

Stream 的优点在于可以让代码更简洁、可读性更好、通过各种Api的组合完成对集合数据的复杂操作、并且可以通过并行处理来提高程序性能。但是需要注意的是,Stream 并不是在所有情况下都比传统的集合操作更好,具体使用时需要根据具体场景进行取舍。

Api学习

stream()

Stream API中的stream()方法用于将集合对象转换为Stream对象。其语法如下:

Stream<T> stream()

其中,T是集合中元素的类型。stream()方法返回一个Stream对象,其中包含了集合中所有元素的信息。

下面是一个示例代码,演示如何使用stream()方法将一个List对象转换为Stream对象:

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

在上面的代码中,首先通过Arrays.asList()方法创建了一个包含五个整数的List对象numbers。接着,使用stream()方法将numbers转换为Stream对象。

需要注意的是,由于Stream对象是惰性求值的,因此在调用stream()方法时并不会立即开始遍历集合。只有在使用Stream对象中的方法时,才会开始遍历集合并执行相应的操作。因此,可以通过链式调用Stream对象中的多个方法,来实现一系列操作的连续执行。例如开头的那段代码,对就是这个:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
    .filter(n -> n % 2 == 0)
    .mapToInt(Integer::intValue)
    .sum();

filter()

Stream API中的filter()方法用于根据指定的条件过滤集合中的元素,并返回一个包含满足条件的元素的新的Stream对象。其语法如下:

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

其中,T是集合中元素的类型,Predicate是一个函数式接口,用于表示一个接受一个参数并返回一个布尔值的函数。在调用filter()方法时,需要将一个Predicate对象作为参数传入,表示要对集合中的元素进行过滤的条件。

下面是一个示例代码,演示如何使用filter()方法过滤List中的偶数:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

在上面的代码中,首先使用stream()方法将List对象转换为Stream对象。然后,使用filter()方法过滤出其中的偶数。在这个例子中,使用lambda表达式 `n -> n % 2 == 0` 作为Predicate对象,表示只要集合中的元素模2等于0,就保留该元素。

需要再一次强调的是,Stream对象是惰性求值的,因此调用filter()方法时并不会立即开始遍历集合,而是在调用collect()方法时才开始遍历并执行相应的操作。如果没有进行collect()操作,filter()方法的调用不会对原始集合产生任何影响。

collect()

Stream API中的collect()方法用于将Stream中的元素收集到一个集合中。

collect()方法的语法如下:

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

其中,T是Stream中的元素类型,A是用于中间结果累积的类型,R是collect()方法的返回值类型。collector是一个Collector类型的参数,用于定义收集逻辑,包括如何累积中间结果,如何合并中间结果,以及如何将中间结果转换为最终结果。

Stream API提供了许多预定义的Collector类型,包括toList()、toSet()、toMap()等等,可以根据需求选择合适的Collector类型。除了预定义的Collector类型,也可以自定义Collector类型,实现更复杂的收集逻辑。

又是这一段代码,它演示如何使用collect()方法将一个Stream中的元素收集到一个List中:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> result = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());

在上面的代码中,首先通过Arrays.asList()方法创建了一个包含五个整数的List对象numbers。接着,使用stream()方法将numbers转换为Stream对象,然后使用filter()方法过滤出其中的偶数。最后,使用collect()方法将过滤后的结果收集到一个List对象中

需要注意的是,使用collect()方法收集Stream中的元素时,需要注意线程安全问题。如果在多线程环境中使用Stream API,建议使用线程安全的集合类,或者使用collect()方法的并发版本。例如,可以使用Collectors.toConcurrentMap()方法将Stream中的元素收集到一个线程安全的ConcurrentMap中。

map()

Stream API中的map()方法是一个用于将Stream中的元素映射为另外一种形式的方法。其接受一个函数作为参数,这个函数将被应用到Stream中的每个元素上,产生一个新的Stream,这个Stream中包含了映射后的元素。

map()方法的语法如下:

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

其中,T是原Stream中的元素类型,R是map()方法的返回值类型。mapper是一个Function类型的参数,接受一个T类型的参数,返回一个R类型的结果。

上代码,目的是用map()方法将一个String类型的List中的每个元素转换为大写形式:

List<String> words = Arrays.asList("hello", "world", "java", "stream");
List<String> upperWords = words.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

在上面的代码中,首先通过Arrays.asList()方法创建了一个包含四个String元素的List对象words。接着,使用stream()方法将words转换为Stream对象,然后使用map()方法将每个String元素转换为大写形式。最后,使用collect()方法将转换后的结果收集到一个List对象中。

需要注意的是,在map()方法中,参数mapper可以是一个lambda表达式,也可以是一个方法引用,如上面示例代码中的String::toUpperCase。使用方法引用能够更加简洁地实现转换逻辑。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值