【Java基础】JDK8新特性最佳实践3

简介: 【Java基础】JDK8新特性最佳实践3

8.Collector收集器和集合统计

8.1.collector收集器

  • collect()方法的作用
  • 一个终端操作,用于对流中的数据进行归集操作,collect方法接收的参数是一个Collector
  • 有两个方法重载,在Stream接口里面
//重载方法一 
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R>combiner);  
//重载方法二
<R, A> R collect(Collector<? super T, A, R> collector)
  • Collector的作用
  • 就是收集器,也是一个接口,它的工具类Collectors提供了很多工厂方法
  • Collectors的作用
  • 提供了很多常见的集合的收集
  • Collectors.toList()
public static <T> Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>(
        (Supplier<List<T>>) ArrayList::new,
        List::add,
        (left, right) -> { 
            left.addAll(right); 
            return left; },
        CH_ID
    );
}
  • ArrayList::new,创建一个ArrayList作为累加器
  • List::add,对流中的元素直接加到累加器中
  • reduce,对子任务归集结果直接全部添加到前一个子任务结果中
  • CH_ID是一个unmodifableSet集合

常见的收集器

  • Collector.toMaps():创建一个map收集器
  • Collector.toSet():创建一个set收集器
  • Collector.toCollection():自定义收集器
  •              Collector.toCollection(LinkedList::new)
  •              Collector.toCollection(TreeSet::new)

8.2.joining函数

  • 拼接函数,将集合内的元素按照一定规则拼接起来,Collectors.joining()
//三种重载方法
Collectors.joining() //无参数默认按照空字符拼接
Collectors.joining("-") //一个参数,按照“-”进行分割
Collectors.joining("-","{","}") //三个参数,第一个为分隔符,后两个为前缀后缀
  • 源码

baefce4b36d74d30bd71266ad09e052d.jpeg

38641759913942099f90e2c27584dc07.jpeg

319d759ec4f64e4983b8ae8f6cdc21f5.jpeg

  • 测试
List<String> list = Arrays.asList("SpringBoot","Docker","Java","SpringCloud","Netty");
String collect1 = list.stream().collect(Collectors.joining());
System.out.println(collect1);
String collect2 = list.stream().collect(Collectors.joining("-"));
System.out.println(collect2);
String collect3 = list.stream().collect(Collectors.joining("-", "{", "}"));
System.out.println(collect3);

f06592ff01bd4551a2af247a7a7a7583.jpeg

8.3.partitioningBy分组

  • Collectors.partitioningBy()会根据筛选条件进行分组,返回一个Map<Boolean,List>类型,boolean为true的表示符合条件的,false的为不符合筛选条件的。
  • 源码

 b5e617ce444e4955933cc39c7de82be3.jpeg  

  • 测试
List<String> list = Arrays.asList("Java","SpringBoot","HTML5","CSS3");
Map<Boolean, List<String>> collect = list.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 4));
System.out.println(collect);

3bbf4f38f7954a25ad865e3d8d7ed5e6.jpeg

8.4.groupingBy分组

  • Collectors.groupingBy(),会根据实体Bean的某个属性进行分组,更实用,返回的是Map<String,List>,key为要分组的实体Bean的属性值
  • 源码

dbebeb6b6c1d4bd7bb5323c8fa25e705.jpeg

d79fe376a7664616898599f8ea3a2bdd.jpeg

  • 测试
List<Student> students = Arrays.asList(
      new Student("lx", 23, "北京"),
      new Student("ls", 24, "天津"),
      new Student("zs", 23, "⼴东"),
      new Student("ww", 22, "⼴东"),
      new Student("ld", 20, "北京"),
      new Student("xs", 20, "⼴东"),
      new Student("ok", 25, "北京"));
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(obj -> obj.getProvince()));
//第二种方式
//Map<String, List<Student>> collect1 = students.stream().collect(Collectors.groupingBy(Student::getProvince));
        collect.forEach((key,value) -> {
            System.out.println("----"+key);
            value.forEach(obj-> System.out.println(obj));
        });

8a4680ddcaaf40848476f82be41014cb.jpeg

8.5.counting函数

  • 用于统计groupingBy于分组之后,每组元素的个数
  • 源码

7ab02017a45645eab9d7b28ba8885a3f.jpeg

  • 测试
List<Student> students = Arrays.asList(
       new Student("lx", 23, "北京"),
       new Student("ls", 24, "天津"),
       new Student("zs", 23, "⼴东"),
       new Student("ww", 22, "⼴东"),
       new Student("ld", 20, "北京"),
       new Student("xs", 20, "⼴东"),
       new Student("ok", 25, "北京"));
Map<String, Long> collect1 = students.stream().collect(Collectors.groupingBy(Student::getProvince, Collectors.counting()));
collect1.forEach((key,value) -> {
     System.out.println("---"+key);
     System.out.println("---"+value);
});

55944b8c2806440bbd3f5c0cde14b641.jpeg

8.6.summarizing集合统计

  • 集合相关的统计都能实现,根据实体Bean的某个属性进行统计,求最大值,最小值,总和等等
  • 分类
  • summarizingInt
  • summarizingLong
  • summarizingDouble
  • 测试,统计各个学生的年龄信息
IntSummaryStatistics collect = students.stream().collect(Collectors.summarizingInt(Student::getAge));
System.out.println("平均值:"+collect.getAverage());
System.out.println("总人数:"+collect.getCount());
System.out.println("年龄总和:"+collect.getSum());
System.out.println("最大值:"+collect.getMax());
System.out.println("最小值:"+collect.getMin());

cf3cb39e42a54fc689bba85786f3a31a.jpeg

9.Collection和Lambda实战

(1)需求:求两个集合的交集、差集、去重并集,两集合的各自平均值,总和

(2)创建两个集合

//总价 35
List<VideoOrder> videoOrders1 = Arrays.asList( new VideoOrder("20190242812", "springboot教程", 3), new VideoOrder("20194350812", "微服务SpringCloud", 5), new VideoOrder("20190814232", "Redis教程", 9), new VideoOrder("20190523812", "⽹⻚开发教程", 9), new VideoOrder("201932324", "百万并发实战Netty", 9));
//总价 54
List<VideoOrder> videoOrders2 = Arrays.asList( new VideoOrder("2019024285312", "springboot教程", 3), new VideoOrder("2019081453232", "Redis教程", 9), new VideoOrder("20190522338312", "⽹⻚开发教程", 9), new VideoOrder("2019435230812", "Jmeter压⼒测试", 5), new VideoOrder("2019323542411", "Git+Jenkins持续集成", 7), new VideoOrder("2019323542424", "Idea全套教程", 21));

(3)注意一点要重写equals和hashcode方法

@Override
public boolean equals(Object o) {
    if(o instanceof VideoOrder){
        VideoOrder o1 = (VideoOrder)o;
        return this.title.equals(o1.title);
    }
    return super.equals(o);
}
@Override
public int hashCode() {
    return title.hashCode();
}

(4)计算两个集合的交集

List<VideoOrder> clist = videoOrder1.stream().filter(videoOrder2::contains).collect(Collectors.toList());

(5)计算两个集合的差集

List<VideoOrder> nclist = videoOrder1.stream().filter(obj -> !videoOrder2.contains(obj)).collect(Collectors.toList());

(6)计算两个集合的去重并集

List<VideoOrder> allList = videoOrder1.paralleStream().distinct().collect(Collectors.toList());
allList.addAll(videoOrder2);

(7)计算订单价格的平均值

double avg = videoOrder1.stream().collect(Collectors.averagingInt(VideoOrder::getMoney)).doubleValue();

(8)计算订单价格的总和

Integer sum = videoOrders1.stream().collect(Collectors.summingInt(VideoOrder::getMoney));

c93322dd4d1a4640a5282719775d07fd.jpeg

10.内存空间和异常处理

10.1.新内存空间Matespace

  • JVM 种类有很多,⽐如 Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM,我们讲的是Hotspot才有,JRockit以及J9是没有这个区域
  • JVM内存JDK8之前的HotSpot JVM,有个区域叫做”永久代“(permanent generation),通过在命令行设置参数:-XX:MaxPermSize来设定永久代最大可分配的内存空间
  • 如果JDK8中设置了PermSize和Max PermSize会被忽略并且警告
  • 作用:该块内存主要是被JVM用来存放class和mate信息的,当class被加载loader的时候会被存储到该内存区中,入方法的编译信息及字节码、常量池和符号解析、类的层级信息,字段、名字等
  • java.lang.OutOfMemoryError: PermGen space
  • 异常原因:永久代空间不够,可能类太多导致
  • JDK8使用本地内存存储类元数据信息,叫做元空间(Metaspcae)
  • 在默认情况下Metaspcae的大小至于本地内存大小有关系
  • 常⽤的两个参数
  • -XX:MetaspaceSize=N 指Metaspace扩容时触发FullGC的初始化阈值
  • -XX:MaxMetaspaceSize=N 指⽤于限制Metaspace增⻓的上限,防⽌因为某些情况导致Metaspace⽆限的使⽤本地内存
  • 不管两个参数如何设置,都会从20.8M开始,然后随着类加载越来越多不断扩容调整直到最⼤
  • 查看MetaspaceSize的大小
  • jstat -gc pid

10.2.try-with-resources(JDK7)

  • 自动关流
  • jdk7之前处理异常
    public static void main(String[] args) throws FileNotFoundException {
        String filePath = "F:\\1.txt";
        test(filePath);
    }
    private static void test(String filePath) throws FileNotFoundException {
        OutputStream outputStream = new FileOutputStream(filePath);
        try {
            outputStream.write((filePath+"学习").getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • jdk7之后处理异常
    public static void main(String[] args) throws FileNotFoundException {
        String filePath = "F:\\1.txt";
        test(filePath);
    }
    private static void test(String filePath) throws FileNotFoundException {
        //自动关流,当有多个文件时,直接用;分割就可以
        try (OutputStream outputStream = new FileOutputStream(filePath)){
            outputStream.write((filePath + "学习").getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 实现了AutoCloseable接口的类,在try()里面声明该类实例的时候,try结束后自动i盗用的close方法,这个动作会早于finally里面调用的方法。
  • 不管是否出现异常,try()里面的实例都会被调用close方法。
  • try里面可以声明多个自动关闭的对象,越早声明的对象,会越晚被关掉。
    public static void main(String[] args) throws FileNotFoundException {
        String filePath = "F:\\1.txt";
        test(filePath);
    }
    private static void test(String filePath) throws FileNotFoundException {
        OutputStream outputStream = new FileOutputStream(filePath);
        try {
            outputStream.write((filePath+"学习").getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
  • jdk7之后处理异常
    public static void main(String[] args) throws FileNotFoundException {
        String filePath = "F:\\1.txt";
        test(filePath);
    }
    private static void test(String filePath) throws FileNotFoundException {
        //自动关流,当有多个文件时,直接用;分割就可以
        try (OutputStream outputStream = new FileOutputStream(filePath)){
            outputStream.write((filePath + "学习").getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • 实现了AutoCloseable接口的类,在try()里面声明该类实例的时候,try结束后自动i盗用的close方法,这个动作会早于finally里面调用的方法。
  • 不管是否出现异常,try()里面的实例都会被调用close方法。
  • try里面可以声明多个自动关闭的对象,越早声明的对象,会越晚被关掉。
相关文章
|
5月前
|
Java API 数据处理
Java新特性:使用Stream API重构你的数据处理
Java新特性:使用Stream API重构你的数据处理
Java API 开发者
168 0
|
7月前
|
并行计算 Java API
Java List 集合结合 Java 17 新特性与现代开发实践的深度解析及实战指南 Java List 集合
本文深入解析Java 17中List集合的现代用法,结合函数式编程、Stream API、密封类、模式匹配等新特性,通过实操案例讲解数据处理、并行计算、响应式编程等场景下的高级应用,帮助开发者提升集合操作效率与代码质量。
329 1
|
7月前
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
818 1
|
7月前
|
缓存 安全 Java
Java 并发新特性实战教程之核心特性详解与项目实战
本教程深入解析Java 8至Java 19并发编程新特性,涵盖CompletableFuture异步编程、StampedLock读写锁、Flow API响应式流、VarHandle内存访问及结构化并发等核心技术。结合电商订单处理、缓存系统、实时数据流、高性能计数器与用户资料聚合等实战案例,帮助开发者高效构建高并发、低延迟、易维护的Java应用。适合中高级Java开发者提升并发编程能力。
276 0
|
关系型数据库 Java MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【9月更文挑战第6天】在Linux环境下安装JDK 1.8、Tomcat和MariaDB是搭建Java Web应用的关键步骤。本文详细介绍了使用apt-get安装OpenJDK 1.8、下载并配置Tomcat,以及安装和安全设置MariaDB(MySQL的开源分支)的方法。通过这些步骤,您可以快速构建一个稳定、高效的开发和部署环境,并验证各组件是否正确安装和运行。这为您的Java Web应用提供了一个坚实的基础。
260 0
|
Java 关系型数据库 MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【8月更文挑战第19天】在Linux上搭建Java Web应用环境,需安装JDK 1.8、Tomcat及MariaDB。本指南详述了使用apt-get安装OpenJDK 1.8的方法,并验证其版本。接着下载与解压Tomcat至`/usr/local/`目录,并启动服务。最后,通过apt-get安装MariaDB,设置基本安全配置。完成这些步骤后,即可验证各组件的状态,为部署Java Web应用打下基础。
294 1
|
IDE Java 测试技术
Java零基础(4) - JDK、IntelliJ IDEA的安装和环境变量配置
【8月更文挑战第4天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
410 0
Java零基础(4) - JDK、IntelliJ IDEA的安装和环境变量配置
WXM
|
Oracle Java 关系型数据库
Java JDK下载安装及环境配置超详细图文教程
Java JDK下载安装及环境配置超详细图文教程
WXM
12053 3
|
Oracle Java 关系型数据库
Java官网下载JDK21版本详细教程(下载、安装、环境变量配置)
Java官网下载JDK21版本详细教程(下载、安装、环境变量配置)