Effective Java~46. 优先选择Stream 中无副作用的函数
纯函数(pure function)的结果仅取决于其输入:它不依赖于任何可变状态,也不更新任何状态。
坏味道
// Uses the streams API but not the paradigm--Don't do this!
Map<String, Long> freq = new HashMap<>();
try (Stream<String> words = new Scanner(file).tokens()) {words.forEach(word -> {freq.merge(word.toLowerCase(), 1L, Long::sum);});
}
forEach 操作应仅用于报告流计算的结果,而不是用于执行计算
// Proper use of streams to initialize a frequency table
Map<String, Long> freq;
try (Stream<String> words = new Scanner(file).tokens()) {freq = words.collect(groupingBy(String::toLowerCase, counting()));
}
Collectors有三个这样的收集器: toList() 、toSet() 和toCollection(collectionFactory) 。它们分别返回集合、列表和程序员指定的集合类型
// Pipeline to get a top-ten list of words from a frequency table
List<String> topTen = freq.keySet().stream().sorted(comparing(freq::get).reversed()).limit(10).collect(toList());
toMap(keyMapper、valueMapper)最简单的映射收集器 ,它接受两个函数,一个将流元素映射到键,另一个映射到值
// Using a toMap collector to make a map from string to enum
private static final Map<String, Operation> stringToEnum =Stream.of(values()).collect(toMap(Object::toString, e -> e));
如果流中的每个元素都映射到唯一键,则这种简单的 toMap 形式是完美的。 如果多个流元素映射到同一个键,则管道将以 IllegalStateException 终止。
toMap 的三个参数形式对于从键到与该键关联的选定元素的映射也很有用。例如,假设我们有一系列不同艺术家(artists)的唱片集(albums),我们想要一张从唱片艺术家到最畅销专辑的 map。这个收集器将完成这项工作。
public class Apple implements Serializable {/*** 颜色.*/private String color;/*** 总量.*/private Integer weight;//get/set...
}
final Map<String, Apple> singleMap = list.stream().collect(Collectors.toMap(Apple::getColor, it -> it, BinaryOperator.maxBy(Comparator.comparing(Apple::getWeight))));
请注意,比较器使用静态工厂方法 maxBy ,它是从 BinaryOperator 静态导入的。 此方法将 Comparator<T>转换为 BinaryOperator<T> ,用于计算指定比较器隐含的最大值。
toMap 的三个参数形式的另一个用途是产生一个收集器,当发生冲突时强制执行 last-write-wins 策略。 对于许多流,结果是不确定的,但如果映射函数可能与键关联的所有值都相同,或者它们都是可接受的,则此收集器的行为可能正是您想要的:
// Collector to impose last-write-wins policy
final Map<String, Apple> singleMap = list.stream().collect(Collectors.toMap(Apple::getColor, it -> it, (oldVal, newVal) -> newVal));
toMap 的第三个也是最后一个版本采用第四个参数,它是一个 map 工厂,用于指定特定的 map 实现,例如EnumMap 或 TreeMap 。
groupingBy 方法,该方法返回收集器以生成基于分类器函数(classifier function) 将元素分组到类别中的 map。 分类器函数接受一个元素并返回它所属的类别。 此类别来用作元素的 map 的键。
Map<String, Long> freq = words.collect(groupingBy(String::toLowerCase, counting()));
join ,它仅对 CharSequence 实例(如字符串)的流进行操作。 在其无参数形式中,它返回一个简单地连接元素的收集器。
List<String> items =Arrays.asList("apple", "apple", "banana");
final String str = items.stream().collect(Collectors.joining(",", "[", "]"));//[apple,apple,banana]
Effective Java~46. 优先选择Stream 中无副作用的函数相关推荐
- Effective-Java 优先考虑流中无副作用的函数
46. 优先考虑流中无副作用的函数 如果你是一个刚开始使用流的新手,那么很难掌握它们.仅仅将计算表示为流管道是很困难的.当你成功时,你的程序将运行,但对你来说可能没有意识到任何好处.流不仅仅是一个 A ...
- Java 8系列之Stream中万能的reduce
Stream系列: Java 8系列之Stream的基本语法详解 Java 8系列之Stream的强大工具Collector Java 8系列之重构和定制收集器 Java 8系列之Stream中万能的 ...
- Effective Java~45. 谨慎使用Stream
在 Java 8 中添加了 Stream API,以简化顺序或并行执行批量操作的任务. 该 API 提供了两个关键的抽象:流(Stream),表示有限或无限的数据元素序列,以及流管道 (stream ...
- java skip函数_【Java必修课】图说Stream中的skip()和limit()方法及组合使用
1 简介 本文将讲解Java 8 Stream中的两个方法:skip()和limit().这两个方法是Stream很常用的,不仅各自会被高频使用,还可以组合出现,并能实现一些小功能,如subList和 ...
- Effective C# Item45 : 优先选择强异常安全保证
当应用程序捕获一个异常时,代表着我们为应用程序引入了一个"具有破坏性的事件",异常可能会对系统资源或者应用程序的状态有破坏,我们应该避免这种情况发生. Dave Abrahams对 ...
- Effective Java之在细节消息中包含能捕获失败的消息(六十三)
程序为捕获的异常而失败,系统会自动打印该异常的堆栈轨迹,在堆栈中包含该异常的字符串表示法(它的toString方法结果,包含类名,消息细节), 在这种情况下,我们有时看到一长串类名和自动生成的错误消息 ...
- Effective Java之优先使用标准的异常(六十)
Java平台类库提供了一组基本的未受检的异常,他们满足了绝大部分API的异常抛出异常. 为什么优先使用标准异常 1.它使你的API可读性更强,因为它与程序员习惯的用法一致. 2.异常类越少,程序在类装 ...
- Effective Java之在公有类中使用访问方法而非公有域(十四)
1.对于公有类来说,如果类可以在它所在的包的外部进行访问,就提供访问方法,以保留将来改变该类的内部表示法的灵活性. 如果公有域暴露了他的数据域,要想在将来改变它的内部表示法是不可能的,因为公有类的客户 ...
- python无返回值函数_理解Python 中无返回值函数的问题
例如 list 的 append 操作就是无返回值的,换句话说就是不能进行形如 list = [] list.append(1).append(2) 这样的连续操作 注意函数返回的数据类型注意是 li ...
最新文章
- Tomcat 调优及 JVM 参数优化
- 百度地图的简单使用 ——html js
- 2021年技术人员的最佳Linux桌面前5名
- 在ionic/cordova中使用极光推送插件(jpush)
- 从这篇文章可以看出有些错误,由此可以看出,还是看msdn要好的多,这是我的经验
- 平移不变性:Translation Invariance 与 平移同变性:Translation equivariance
- 二叉树前序遍历python输出_Python 二叉树查找 前序 中序 后序遍历
- Codeforces 914D - Bash and a Tough Math Puzzle 线段树,区间GCD
- C语言不调用库函数画直线
- 转:VMware、微软等四种主要的网络IO虚拟化模型
- C++中动态定义一维数组,二维数组,三维数组的方法
- Linux查看版本信息及CPU内核、型号等
- 常用类 (三) ----- BigDecimal和BigInteger大数类
- python多线程提高速度_Python3如何使用多线程升程序运行速度
- python中print说法正确的是_python中的print()输出
- python入门11 元组tuple
- 设备管理系统未来发展的四大趋势
- Unity Editor 查找资源依赖、反向查找资源依赖Dependencies
- win10无法登录到你的账户->注销->重启->桌面初始化(只剩回收站+默认浏览器)等一系列问题出现
- JDK的下载与安装配置教程2022最新