`

Java 8 Stream API 实用指南

    博客分类:
  • java
 
阅读更多
引用
来源:gitbook
作者:阿福

本文作为 Stream API 的 “使用指南”,主要侧重于 “实用”,并不会关注太多的实现细节,当然,不是简单地罗列接口,而是尽可能地向读者展示 Stream API 的全貌。

开始之前

作为 Java API 的新成员,Stream API “允许以声明式的方式处理数据集合”。回顾 “内容介绍” 部分,我们阅读了以下的代码:
代码
  1. class Good {  
  2.   String name;               // 商品名称  
  3.   long price;               // 价格  
  4.   long sales;               // 销量  
  5.   List<String> categories;  // 类别  
  6.   
  7.   // ... 省略 constructor、getter / setter  
  8.   
  9.   // ... 省略 toString  
  10. }  
  11.   
  12. void process(List<Good> goods) {  
  13.   //  
  14.   // 筛选 price > 500 & sales < 200 的商品, 价格最高的 10 件商品, 价格减半(双十一来啦!)  
  15.   //  
  16.   goods.stream()  
  17.     .filter(c -> c.getPrice() > 500 && c.getSales() < 200)  
  18.     .sorted(Comparator.comparing(Good::getPrice).reversed())  
  19.     .limit(10)  
  20.     .forEach(c -> { c.setPrice(c.getPrice() / 2); });  
  21. }  

即使没有 Stream API,我们依然能够通过完成需求,但无法做到如此简洁、清晰。(本文最后的部分,还会进一步探讨 Stream API 在并发方面的优势。)

开始使用 Stream API 之前,我们需要了解,Stream 是什么?有哪些比较重要的概念?为此,我们针对上文的代码绘制了示意图:

图中所示,整个过程就是将 goods 元素集合作为一个 “序列”,进行一组 “流水线” 操作,其中:
  • goods 集合提供了元素序列的数据源,通过 stream() 方法获得 Stream
  • filter / sorted / limit 进行数据处理,“连接起来” 构成 “流水线”
  • forEach 最终执行
需要说明,filter / sorted / limit 的返回值均为 Stream(类似于 Builder 模式),但它们并不立即执行,而是构成了 “流水线”,直到 forEach:最终执行,并且关闭 Stream。因此:
  • 将 filter / sorted / limited 等能够 “连接起来”,并且返回 Stream 的方法称为 “中间操作”(Intermediate)
  • 将 forEach 等最终执行,并且关闭 Stream 的方法称为 “终止操作” (Terminal)

特别地,需要记住:Stream 的中间操作并不是立即执行,而是 “延迟的”、“按需计算”;并且,完成 “终止操作” 后,Stream 将被关闭。

现在,我们应当了解 Stream 的关键概念:数据源、中间操作构成 “流水线”、终止操作,对于 Stream 的定义,我们直接引用 Java doc:
引用
A sequence of elements supporting sequential and parallel aggregate operations.

代码
  1. package java.util.stream;  
  2.   
  3. public interface Stream<T> extends BaseStream<T, Stream<T>> {  
  4.   // ...  
  5. }  

代码所示:Stream 中序列元素的类型,通过泛型表达。对于原始类似,除了包装类外,Stream API 同时提供了原始类型的 Stream:IntStream、LongStream 以及 DoubleStream

本质而言,Stream API 的 “流水线” 操作,最终仍然依赖于迭代,但与使用 Collection API 直接构建迭代的代码不同,Stream API 通过参数的形式接收我们提供的操作,由其内部实现迭代。

而所谓 “我们提供的操作”,请参考 “Lambda 表达式 & 方法引用”。

Lambda 表达式 & 方法引用

Lambda 表达式,或者 λ,虽然并不是新鲜事物,但其越来越受到重视,尤其是 Java 8(以及 C++11)将 Lambda 表达式纳入标准以后。暂且不谈论 “函数式编程” 的话题,我们先了解 Lambda 表达式如何使用。

Lamba 表达式

对于 Java 开发者,匿名类是很常见的东西,例如:
代码
  1. @FunctionalInterface  
  2. interface PriceCalculator {  
  3.   long calculate(Good good);  
  4. };  
  5.   
  6. public void process(List<Good> goods, PriceCalculator calculator) {  
  7.   // 计算商品价格      
  8. }  
  9.   
  10. //  
  11. // 实现 PriceCalculator 接口的匿名类实例,作为 process 参数  
  12. //  
  13. process(goods, new PriceCalculator() {  
  14.   @Override  
  15.   public long calculate(Good good) {  
  16.     return good.getPrice();  
  17.   }  
  18. });  

接口 PriceCalculator 只有一个方法,我们将只有一个抽象方法的接口,称为 “函数式接口”,并以 @FunctionalInterface 进行标记。(注意,Java 8 允许接口提供方法实现,即 “默认方法”,函数式接口必须包含且仅包含一个抽象方法,对于提供实现的默认方法,没有限制)

Lambda 表达式,其本质即为函数式接口的一个实例:
代码
  1. //  
  2. // 示例 #1: args -> { statement; }   
  3. //  
  4. process(goods, (good) -> {  
  5.   return good.getPrice();  
  6. });  
  7.   
  8. //  
  9. // 示例 #2:args -> expression  
  10. //  
  11. process(goods, (good) -> good.getPrice());  

函数式接口中抽象方法的签名即为 Lambda 表达式的签名,称为 “函数描述符”。Lambda 表达式的类型,由 Java 编译器根据上下文推断获得。

方法引用

方法引用,即为特定情况下 Lambda 表达式的简化,例如:
代码
  1. process(goods, Good::getPrice);  

对于 Lambda 表达式到方法引用的简化,我们提供以下规则:
Lambda 表达式 方法引用
(args) -> ClassName.staticMethod(args) ClassName::staticMethod
(arg0, ...) -> arg0.instanceMethod(...) ClassName::instanceMethod
(args) -> expression.instanceMethod(args) expression::instanceMethod

特别的,对于构造函数的方法引用:ClassName::new

开始使用 Stream API

本章节将阐述 Stream 的生成、操作、数据收集,主要介绍 Stream API 的常用接口与辅助方法。为了便于我们试验示例的代码,我们先说明 forEach(Consumer<? super T>)。

正如前面章节所说,forEach(Consumer<? super T>) 是一个 “终止操作”,它遍历 Stream 的元素序列,通过函数式接口 Consumer<? super T> 的 accept(T) 执行特定操作。Consumer<? super T> 的声明:
代码
  1. @FunctionalInterface  
  2. public interface Consumer<T> {  
  3.   void accept(T);  
  4. }  

以下的阐述中,将通过 forEach(System.out::println) 将 Stream 的元素序列输出。

生成 Stream

由集合 & 数组生成 Stream

Stream 作为元素的 “序列”,自然而然地,我们想到通过集合、数组生成 Stream。

Java 8 的 Collection 接口添加了 Stream<E> stream() 方法,由集合生成 Stream,例如:
代码
  1. //  
  2. // 输出商品集合  
  3. //  
  4. void print(List<Good> goods) {  
  5.   goods.stream().forEach(System.out::println);  
  6. }  

java.util.Arrays 提供了 stream(T[]) 的静态方法,由 T[] 数组生成 Stream:
代码
  1. //  
  2. // 输出商品数组  
  3. //  
  4. void print(Good[] goods) {  
  5.   Arrays.stream(goods).forEach(System.out::println);  
  6. }  

特别地,当数组元素类型 T 是原始类型,静态方法 stream(T[]) 将返回原始类型的 Stream。

通过集合或数组获得的 Stream,是 “有限” 的。

直接创建 Stream

除了由集合和数组生成 Stream,Stream API 提供了静态方法 Stream.generate(Supplier<T>)、Stream.iterator(final T, final UnaryOperator<T>),直接创建 Stream。

Stream.generate(Supplier<T>) 通过参数 Supplier<T> 获取 Stream 序列的新元素
代码
  1. //  
  2. // 生成指定数量的商品并输出  
  3. //  
  4. void generate(int number) {  
  5.   Stream.generate(Good::new).limit(number).forEach(System.out::println);  
  6. }  


Stream.iterator(final T, final UnaryOperator<T>) 提供了一种 “迭代” 的形式:第一个元素,以及第 n 个元素到第 n + 1 个元素的生成方式 UnaryOperator<T>。
代码
  1. //  
  2. // 生成指定数量的序列 124816 ... 并输出  
  3. //  
  4. void generateSequence(int number) {  
  5.   Stream.iterate(0, n -> n * 2).limit(number).forEach(System.out::println);  
  6. }  

通过 Stream.generate(Supplier<T>)、Stream.iterator(final T, final UnaryOperator<T>),将产生 “无限的” Stream,以上的示例中,使用 limit 进行了 Stream 截断。

操作 Stream

filter

filter 是 “中间操作”,以 Predicate<? super T> 的实例作为参数,进行 Stream 过滤,仅保留符合条件的元素。Predicate<? super T> 作为常用的函数式接口,其声明如下:
代码
  1. @FunctionalInterface  
  2. public interface Predicate<T> {  
  3.     boolean test(T);   
  4. }  

例如:
代码
  1. //  
  2. // 过滤高于指定价格的商品  
  3. //  
  4. void filterByPrice(List<Good> goods, long price) {  
  5.   goods.stream().filter(c -> c.getPrice() > price).forEach(System.out::println);  
  6. }  

anyMatch / allMatch / noneMatch

anyMatch、allMatch、noneMatch,都是 “终止操作”,与 filter 接收相同的参数,其功能顾名思义,例如:
代码
  1. //  
  2. // 检查商品集合是否包含指定名称的商品  
  3. //  
  4. boolean hasGoodWithName(List<Good> goods, String name) {  
  5.   return goods.stream().anyMatch(c -> name.equals(c.getName()));  
  6. }  

findAny / findFirst

findAny、findFirst,都是 “终止操作”,分别获取 Stream 元素序列的任意元素和第一个元素:
代码
  1. //  
  2. // 获取商品集合中任意名称为指定名称的商品  
  3. //  
  4. Optional<Good> findAnyGoodWithName(List<Good> goods, String name) {  
  5.   return goods.stream().filter(c -> name.equals(c.getName())).findAny();  
  6. }  

findAny、findFirst 的返回值都是 Optional<T> 类型,避免了 Stream 序列为空时返回 null。关于 Optional<T> 类型,不属于本文的范围,请参阅 Java doc。

相比较于 findFisrt,findAny 更适合于并发的场景。

map

map 是中间操作,将 Stream 序列的元素映射为其他的元素,以 Function<? super T, ? extends R> 作为参数,其声明如下:
代码
  1. @FunctionalInterface  
  2. public interface Function<T, R> {  
  3.     R apply(T);  
  4. }  

代码所示,Function<? super T, ? extends R> 提供了 Stream 序列的元素映射为其他元素的途径,例如:
代码
  1. //  
  2. // 输出商品的名称  
  3. //  
  4. void printName(List<Good> goods) {  
  5.   goods.stream().map(Good::getName).forEach(System.out::println);  
  6. }  

此外,Stream 提供 mapToInt、mapToLong、mapToDouble,将 Stream 映射为原始类型 Stream。

flatMap

map 直接将 Stream 序列的元素映射到新的元素,假如 map 映射获得的是 Stream,flatMap 能够将各个 Stream 的元素合并到一个 Stream 中,例如:
代码
  1. //  
  2. // 获取商品集合的分类  
  3. //  
  4. void getCategories(List<Good> goods) {  
  5.   goods.stream().flatMap(c -> c.getCategories().stream()).forEach(System.out::println);  
  6. }  

distinct

distinct 是 “中间操作”,即去重,去重的依据即为 Stream 序列元素类型的 equals 和 hashCode 方法,例如:
代码
  1. //  
  2. // 获取商品名称,去重  
  3. //  
  4. void distinctGoodNames(List<Good> goods) {  
  5.   goods.stream().map(Good::getName).distinct().forEach(System.out::println);  
  6. }  

sorted

sorted 是 “中间操作”,以 Comparator<? super T> 作为参数,将 Stream 序列元素排序,Comparator<? super T>:
代码
  1. //  
  2. // 商品按照价格升序排列  
  3. //  
  4. void sortGoods(List<Good> goods) {  
  5.   goods.stream().sorted(Comparator.comparing(Good::getPrice)).forEach(System.out::println);  
  6. }  

示例代码中,使用辅助方法 Comparator<T> comparing(Function<? super T, ? extends U>) 生成了 Comparator<? super T> 实例。

“内容介绍” 部分的 reversed(),同样是 Comparator<T> 的方法,并提供了默认实现,用于排序时,即可实现排序 “取反”。

limit / skip

limit / skip 是 “中间操作”,接收 long 类型的参数,实现 Stream 序列元素的截取和跳过:
代码
  1. //  
  2. // 获得第 page 页的商品,每页商品数量为 page_size  
  3. //  
  4. void listGoods(List<Good> goods, int page, int page_size) {  
  5.   goods.stream().skip((page - 1) * page_size).limit(page).forEach(System.out::println);  
  6. }  

收集数据


count / min / max
count 是终止操作,将直接返回 Stream 的元素数量:
代码
  1. //  
  2. // 获取高于指定价格的商品数量   
  3. //  
  4. long countGoodsOverPrice(List<Good> goods, long price) {  
  5.   return goods.stream().filter(c -> c.getPrice() > price).count();  
  6. }  

min / max,以 Comparator<? super T> 作为参数,返回最小值和最大值。对于原始类型 Stream,min / max 无参数,例如:
代码
  1. //  
  2. // 获取最高的商品价格  
  3. //  
  4. OptionalLong maxGoodPrice(List<Good> goods) {  
  5.   return goods.stream().mapToLong(Good::getPrice).max();  
  6. }  

示例代码中,LongStream 的 max 方法返回类型为 OptionalLong,即为原始类型的 Optional<T>。

reduce

reduce,“归约”,是 “终止操作”,用于将 Stream 序列归约到一个具体的值,其声明,如下:
代码
  1. //  
  2. // 提供初始值,以及两个 Stream 序列元素结合产生新值的方法  
  3. //  
  4. T reduce(T, BinaryOperator<T>);  
  5.   
  6. //  
  7. // 提供两个 Stream 序列元素结合产生新值的方法,没有初始值,但通过 Optional<T> 避免 Stream 为空时返回 null  
  8. //  
  9. Optional<T> reduce(BinaryOperator<T>);  
  10.   
  11. //  
  12. // 归约到新的类型:提供初始值,新值与 Stream 元素结合的方法,以及两个新值结合的方法  
  13. //  
  14. <U> U reduce(U, BiFunction<U, ? super T, U>, BinaryOperator<U>);  

例如:
代码
  1. long getTotalSalesAmount(List<Good> goods) {  
  2.   //  
  3.   // 获取 goods 集合的销售总额  
  4.   //  
  5.   return goods.stream().reduce(0L, (amount, good) -> amount + good.getSales() * good.getPrice(),(left, right) -> left + right);  
  6. }  

或者:
代码
  1. long getTotalSalesAmount(List<Good> goods) {  
  2.   //  
  3.   // 获取 goods 集合的销售总额  
  4.   //  
  5.   return goods.stream().mapToLong(c -> c.getPrice() * c.getSales()).reduce(0, Long::sum);  
  6. }  

collect

作为 “终止操作”,collect 即 “收集数据”。collect 以 “收集器” Collector<? super T, A, R> 作为参数,通常,我们使用 Collectors 提供的辅助函数获得 “收集器” 实例。

常用的辅助函数

toList / toSet    
    
代码
  1. // // 获取商品名称的集合 // List<String>  
  2.     > getGoodNames(List<Good> goods) {   return  
  3.     > goods.stream().map(Good::getName).collect(Collectors.toList()); }  
  4.     >   

toSet 与 toList 相似,但其返回结果为 Set。

groupingBy

代码
  1. // // 将商品集合按照价格分组 // Map<Long, List<Good>>  
  2.     > groupGoodByPrice(List<Good> goods) {   return  
  3.     > goods.stream().collect(Collectors.groupingBy(Good::getPrice)); }  
  4.     >   
   
partitioningBy

partitioningBy 与 groupingBy 类似,但其得到分组的键类型为 Boolean,即 true & false,最多两组:
代码
  1. // // 根据是否超过指定销量将商品集合分组 // Map<Boolean, List<Good>>  
  2.     > partitionGoodWithSales(List<Good> goods, long sales) {   return  
  3.     > goods.stream().collect(Collectors.partitioningBy(c -> c.getSales() >=  
  4.     > sales)); }   
   
reducing

Collectors.reducing 参数与 Stream.reduce 一致,其获得的 “收集器” 实例,作为 collect 参数,能够与 reduce 获得相同的结果。

根据是否需要存储中间状态,Stream 操作能够划分为 “无状态操作”、“有状态操作”。“无状态操作”,例如:filter、map;“有状态操作”,例如:limit、sorted 等,并且,对于 “有状态操作”,亦根据中间状态存储的要求,其区分 “有界”(例如:limit)、“无界”(例如:sorted)。

并行

通过 “并行 Stream” 即可获得 Stream API 的并行能力,例如:
代码
  1. //  
  2. // 获取最高的商品价格  
  3. //  
  4. OptionalLong maxGoodPrice(List<Good> goods) {  
  5.   return goods.stream().parallel().mapToLong(Good::getPrice).max();  
  6. }  

代码所示,通过 Collection 接口的 parallelStream()、 BaseStream 接口的 parallel() 方法,都能够获得 “并行 Stream”。

并行 Stream 内部是基于 ForkJoinPool 模型获得并行能力,其默认线程数量即为通过 Runtime.getRuntime().availableProcessors() 获得的线程数。

不过,关于并行,两件事必须注意:一方面,正确性,避免 Stream 处理过程中共享可变状态;另一方面,务必记住,并行未必能够提高性能,通常适用于 Stream 元素数量大、或单个元素处理非常耗时的场景。

写在最后

请在阅读完本文后,尝试解答以下问题,最终的答案我们线上交流见 ^_^

1. 以下代码执行,将输出什么?
代码
  1. String[] words = { "a""bb""ccc""dddd""eeee" };  
  2. Arrays.stream(words).filter(c -> { System.out.println(c); return true; }).limit(1).collect(Collectors.toList());  

2. 分别运用 Stream API 的 reduce、collect 方法实现以下方法:
代码
  1. long getTotalSalesAmount(List<Good> goods) {  
  2.   //  
  3.   // 获取 goods 的销售总金额  
  4.   //  
  5. }  

3. 通过 Stream API 实现以下方法:
代码
  1. void printFibonacciSequence(int n) {  
  2.   //  
  3.   // 输出斐波那契数列的前 n 个数  
  4.   //  
  5. }  

4. 通过 Stream API 改造以下代码: (提示,需要了解 collect 方法的参数类型
代码
  1. Collector<T, A, R>)  
  2. class SaleRecord {  
  3.     String recordId;  // 销售记录 Id  
  4.     int goodId;       // 商品 Id  
  5.     int promotionId; // 促销活动 Id  
  6.     long price;       // 价格  
  7.     long sales;       // 数量  
  8. }  
  9.   
  10. class SalesAggregation {  
  11.     int goodId;       // 商品 Id  
  12.     int promotionId; // 促销活动 Id  
  13.     long amount;     // 金额  
  14. }  
  15.   
  16. //  
  17. // 聚合  
  18. //  
  19. List<SalesAggregation> aggregate(List<SaleRecord> saleRecords) {  
  20.   Map<String, SalesAggregation> salesAggregations = new HashMap<>();  
  21.   for (SaleRecord saleRecord : saleRecords) {  
  22.     String key = String.format("%d_%d", saleRecord.goodId, saleRecord.promotionId);  
  23.     if (salesAggregations.containsKey(key)) {  
  24.       salesAggregations.get(key).amount = salesAggregations.get(key).amount + saleRecord.price * saleRecord.sales;  
  25.     } else {  
  26.       SalesAggregation salesAggregation = new SalesAggregation();  
  27.       salesAggregation.goodId = saleRecord.goodId;  
  28.       salesAggregation.promotionId = saleRecord.promotionId;  
  29.       salesAggregation.amount = saleRecord.price * saleRecord.sales;  
  30.   
  31.       salesAggregations.put(key, salesAggregation);  
  32.     }  
  33.   }  
  34.   
  35.   return new ArrayList<>(salesAggregations.values());  
 
来自: gitbook
分享到:
评论

相关推荐

    Java8 Stream API 详细使用方法与操作技巧指南

    Java8 Stream API 详细使用方法与操作技巧指南 Java 8 引入了 Stream API,这是一个重要的特性,允许开发者以一种声明式的方式对数据进行处理。Stream 翻译过来是“流”,它可以看做是一个可操作的数据集序列,具有...

    Java 8 API 中版chm手册

    Java 8 API 中版chm手册是一份详细记录了Java 8编程接口的参考资料,它为开发者提供了关于Java 8新特性和已有组件的全面指南。这份手册是中英双语版本,中文版包含了所有核心Java类库和API的详细说明,方便中国地区...

    Java1.8API中文手册

    Java 8 引入了Stream API,这是一组用于处理集合的新工具,可以进行高效且易于理解的并行数据处理。例如,可以使用`map()`、`filter()`、`reduce()`等方法对集合进行操作,实现函数式编程风格。Lambda表达式的引入...

    Java 8流(Stream)API反转数组的深入指南

    Java 8的流API为数组反转提供了一种新的解决方案,它通过声明式编程简化了代码的编写。然而,开发者需要根据具体的应用场景和性能要求,选择最合适的方法。无论是流API还是传统的循环方法,都有其适用的场景和优势。...

    java1.8中文API

    Java 1.8版本引入了许多新特性,如Lambda表达式、Stream API、方法引用来增强代码的简洁性和效率。 2. **Lambda表达式** Lambda表达式是Java 1.8中的重大改进,它允许开发者以更简洁的方式表示匿名函数。这种语法...

    如何在java 8 stream表达式实现if/else逻辑

    在Java 8 Stream 表达式中,使用filter方法实现if/else逻辑是一种非常实用的方法。这种方法可以使代码变得更加简洁和易读,并且可以避免臃肿的业务逻辑。同时,使用filter方法也可以更好地实现函数式编程的思想。 ...

    JAVA API 1.80 中文版

    Java API 1.80 中文版是Java开发者的重要参考资料,它详细定义了Java平台标准版(Java SE)8中的各种类库、接口和方法。这个API规范是开发者理解和使用Java编程语言的关键工具,帮助他们有效地利用Java 8的功能进行...

    Java jdk api 1.8中文帮助手册

    2. **Stream API**:作为Java 8的核心特性,Stream API允许对集合进行声明性处理,提供了一种高效且易读的方式来处理数据。它支持序列化操作,可以方便地并行执行,极大提高了处理大量数据的效率。 3. **方法引用和...

    java12_api.7z

    - **Stream API增强**:Java 12可能对Stream API进行了优化,如新的流操作或者性能提升,以支持更高效的数据处理。 - **Socket通道的改进**:可能改进了SocketChannel的读写性能,以提高网络编程的效率。 3. **...

    JAVA API1.8.rar

    2. **Stream API**:Stream API是Java 8的重要特性,它提供了一种声明式处理数据的方式,适用于大量数据的并行处理。Stream API可以与集合、数组以及其他数据源一起工作,支持过滤、映射、归约等操作,提高了数据...

    Java 实用系统开发指南[彭晨阳]

    此外,Java集合框架也是系统开发中的重要部分,包括ArrayList、LinkedList、HashMap等数据结构的使用,以及Stream API的引入,都使得数据操作更加简洁高效。 文件08.pdf可能涉及的是Java的网络编程,这部分内容会...

    Java 8新特性终极指南

    Java 8 是一个里程碑式的版本,它引入...通过引入Lambda表达式、Stream API和日期时间API等,Java 8成功地融合了函数式编程的思想,为开发者提供了更多选择和灵活性。学习和掌握这些新特性对于Java程序员来说至关重要。

    帮助文档中文版java8 jdk API

    这个“帮助文档中文版java8 jdk API”旨在为中文使用者提供清晰易懂的Java 8 API参考指南。 API(Application Programming Interface)是软件开发中的一个重要概念,它定义了软件系统中不同组件之间交互的接口和...

    java jdk 1.8 API帮助文档,中文、英文、中英对照全三份.7z

    4. Date和Time API的改进:Java 8引入了全新的java.time包,替代了原有的日期和时间API,提供了更强大、更易于使用的日期和时间处理功能。 5. Nashorn JavaScript引擎:Java 1.8引入了一个内置的JavaScript引擎,...

    java9 sdk api specification docs API参考文档 英文版 HTML格式

    4. Stream API增强:Java 9对Stream API进行了扩展,添加了`IntStream.ofChars()`、`LongStream.ofCodePoints()`等方法,使得处理字符和码点更加方便。 5. 集合工厂方法:对`List`、`Set`和`Map`接口增加了新的工厂...

    Java8开发指南

    3. **流(Stream)**:Java 8的流API提供了一种对集合进行声明式处理的新方式,可以方便地进行过滤、映射、归约等操作。流支持串行和并行处理,极大地提高了大规模数据处理的效率。 4. **方法引用**:在Java 8中,...

    Java_api_1.8_中文版

    API使用说明.docx文件可能是对如何有效使用Java API 1.8的详细指南,包括如何查找和理解API文档,以及在实际项目中如何应用这些API。阅读这份文档将有助于开发者快速上手并熟练掌握Java 1.8的API。

    Java_1.8_API文档,中文版本

    API(Application Programming Interface)文档是编程时的重要指南,它定义了Java语言提供的所有公共类和接口,以及它们的成员变量、方法和构造函数。以下是一些关键的Java 1.8 API知识点: 1. **Lambda表达式**:...

    Java8新特性终极指南Java开发Java经验技巧共27

    5. **日期与时间API**:Java 8对日期和时间API进行了全面重构,提供了`java.time`包,包括`LocalDate`, `LocalTime`, `LocalDateTime`, `ZonedDateTime`等类,取代了旧的`java.util.Date`和`java.util.Calendar`,...

    java使用stream流处理枚举信息的代码实例

    在Java编程中,Stream API是Java 8引入的一个强大特性,它使得集合操作更为简洁、易读且高效。本实例将展示如何利用Stream API处理枚举(Enumeration)信息,从而提高代码的可读性和性能。首先,我们来理解枚举和...

Global site tag (gtag.js) - Google Analytics