写点什么

【函数式编程实战】(七) Collection 在 Java8 和 9 中的增强

  • 2022 年 7 月 26 日
  • 本文字数:3026 字

    阅读完需:约 10 分钟


前言📫 作者简介:小明 java 问道之路,专注于研究计算机底层,就职于金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的设计和架构📫 

🏆 Java 领域优质创作者、阿里云专家博主、华为云专家🏆

🔥 如果此文还不错的话,还请👍关注、点赞、收藏三连支持👍一下博主哦

导读

​Collection、Map API 在 java8 以后的版本重大更新就是引入了流,添加了多个默认方法,例如 Arrays.asList、.of、remove*、replace*、sort、forEach、merge 等等,介绍了变化最大的一个数据结构 ConcurrentHashMap

一、集合工厂(Arrays.asList、List.of、Set.of、Map.of)

java8、9 引入了新方法,例如 Arrays.asList、List.of、Set.of 可以很便捷的创建 Collection 及其子类

Arrays.asList 是一个静态工厂,该方法适用于对象型数据的数组(String、Integer…),不建议使用于基本数据类型的数组(因为会被当成一个整体的对象),将数组与 List 列表链接起来:当更新其一个时,另一个自动更新,不支持 add()、remove()、clear() 等方法

public static void main(String[] args) {    // 该方法适用于对象型数据的数组(String、Integer…)    String[] strings = {"aa", "bb", "cc"};    List<String> stringList = Arrays.asList(strings);
// 该方法不建议使用于基本数据类型的数组(byte,short,int,long,float,double,boolean) int[] ints = new int[]{1, 2, 3}; List intList = Arrays.asList(ints); System.out.println(Arrays.toString(intList.toArray()));
// 将数组与List列表链接起来:当更新其一个时,另一个自动更新 stringList.set(0, "dd"); System.out.println(stringList + " == " + Arrays.toString(strings));
// java.lang.UnsupportedOperationException stringList.add(3, "ee");}
复制代码

List.of Arrays.asList、Set.of 创建不可变的 set 集合,如果有重复值 java.lang.IllegalArgumentException: duplicate element:、Map.of 交替的以列表中的元素作为键值对

public static void main(String[] args) {    // 该方法适用于对象型数据的数组    List<String> list = List.of("aa", "bb", "cc");
// 创建不可变的set集合,如果有重复值 java.lang.IllegalArgumentException: duplicate element: Set<String> set = Set.of("aa", "bb", "cc");
// 交替的以列表中的元素作为键值对 Map<? extends Serializable, String> map = Map.of(123, "aa", "bb", "cc");}
复制代码

二、List、Set 方法增强(removeIf、replaceAll、sort)​

​API 是不断演进的,前几讲说过,java 想在 go、python 等语言中保持活力需要不断迭代,不断接收新的需求和适配新型的硬件

removeIf,可以移除集合中满足某个条件的所有元素,作用是按照一定规则过滤集合中的元素,这个方法和 Stream 流中的 filter 方法不一样,filter 不会对数据源改变

replaceAll ,可以对集合中每个元素执行操作并返回替换后的结果集,类似于 Stream 流中的 map 方法,map 是生成新元素,replaceAll 是修改集合元素

public static void main(String[] args) {    List<OrderInfo> orderInfos = Arrays.asList(new OrderInfo("456", BigDecimal.ONE),            new OrderInfo("123", BigDecimal.TEN));
// 订单号又小到大排序 orderInfos.sort(Comparator.comparing(OrderInfo::getOrderId)); System.out.println(orderInfos); // 订单金额又大到小排序 orderInfos.sort((o1, o2) -> o1.getOrderAmt().compareTo(o2.getOrderAmt()) < 0 ? 1 : -1); System.out.println(orderInfos);
// 注:不可是 .of 工厂创建的集合 orderInfos.replaceAll(orderInfo -> new OrderInfo("123", BigDecimal.ONE)); System.out.println(orderInfos);
// 注:不可是Arrays.asList工厂创建的集合 orderInfos.removeIf(orderInfo -> "456".equals(orderInfo.getOrderId())); System.out.println(orderInfos);}
复制代码

sort,Arrays.sort 是我们常用来排序数组的方法,不止如此,其实 Collections.sort 方法中也是直接拿到集合中的元素数组作为入参直接调用 Arrays.sort 方法的。

legacyMergeSort 是一个插入排序+分治思想+归并的排序思路,ComparableTimSort 算法采取了分治+归并的排序思想,对数组内元素进行排序的,当元素没有具体值时,则会根据数组中的假定的比较器 Comparable.compareTo 进行元素的比较排序

​三、Map 方法增强(forEach、Entry.comparingBy*、compute*、remove、replace*、merge)

Map 增强最多,增加了多个新方法,forEach 可以遍历 map 中每个元素,sorted 按照 odrId 排序,,ap+.entrySet().stream()转换成 Streeam 流,remove/replace/compute 前面介绍过,这里不再追叙。

public static void main(String[] args) {    Map<String, OrderInfo> orderInfos = Map.of("456", new OrderInfo("456", BigDecimal.ONE),            "123", new OrderInfo("123", BigDecimal.TEN));
// forEach 可以遍历map中每个元素 orderInfos.forEach((odrId, orderInfo) -> System.out.println(odrId));
// sorted 按照odrId排序 orderInfos.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(System.out::print); System.out.println();
// merge两个map Map<String, OrderInfo> orderInfoMap0 = Map.of("456", new OrderInfo("456", BigDecimal.ONE)); Map<String, OrderInfo> orderInfoMap1 = Map.of("456", new OrderInfo("456", BigDecimal.ONE)); Map<String, OrderInfo> orderInfoMap = new HashMap<>(orderInfoMap0); orderInfoMap1.forEach((o1, o2) -> orderInfoMap.merge(o1, o2, (k1, k2) -> k2)); orderInfoMap.entrySet().stream().forEachOrdered(System.out::print);}
复制代码

四、ConcurrentHashMap 增强​

​ConcurrentHashMap 改良数据结构,原 ConcurrentHashMap 使用 桶(数组+链表,List 实现),但是数据存储在桶中必然需要 hash 值访问,如果大量 key 返回一样的 hash 值,他的查询的时间复杂度就是 O(n),为了改善性能改为,数组+链表+红黑树(也叫 sorted tree 排序树)

ConcurrentHashMap 提供了一个新的方法计数,size()方法和 mappingCount()方法的有什么异同呢?size()最大值是 Integer 类型的最大值,但是 Map 的 size 可能超过 MAX_VALUE, 所以还有一个方法 mappingCount(),JDK 的建议使用 mappingCount() 而不是 size()。KeySetView 将 ConcurrentHashMap 视图作为 Set ,其中可以通过映射到公共值来可选地启用添加。

public static void main(String[] args) {    Map map = Map.of("456", new OrderInfo("456", BigDecimal.ONE),            "123", new OrderInfo("123", BigDecimal.TEN));    ConcurrentHashMap hashMap = new ConcurrentHashMap(map);
// ConcurrentHashMap计数 System.out.println(hashMap.mappingCount());
// set视图 ConcurrentHashMap.KeySetView keySetView = hashMap.keySet(); System.out.println(keySetView.getMap()); System.out.println(keySetView);}
复制代码

总结 

Collection、Map API 在 java8 以后的版本重大更新就是引入了流,添加了多个默认方法,例如 Arrays.asList、.of、remove*、replace*、sort、forEach、merge 等等,介绍了变化最大的一个数据结构 ConcurrentHashMap

发布于: 2 小时前阅读数: 10
用户头像

物有本末,事有终始。知所先后,则近道矣 2020.03.20 加入

🏆CSDNJava领域优质创作者/阿里云专家博主/华为云专家 📫就职某大型金融互联网公司后端高级工程师 👍专注于研究计算机底层/Java/架构/设计模式/算法

评论

发布
暂无评论
【函数式编程实战】(七) Collection在Java8和9中的增强_Lambda_小明Java问道之路_InfoQ写作社区