Java8新特性/java

news2024/11/28 4:02:18

1.lambda表达式

区别于js的箭头函数,python、cpp的lambda表达式,java8的lambda是一个匿名函数,java8运行把函数作为参数传递进方法中。

  • 语法格式

    (parameters) -> expression 或
    (parameters...) ->{ statements; }
    
  • 实战

    1. 替代匿名内部类:java8之前如果想把方法传给函数(动态传递参数),那么需要匿名内部类

      • Runnable接口

        new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println("The runable now is using!");
                    }
        }).start();
        //用lambda
        new Thread(() -> System.out.println("It's a lambda function!")).start();
        
        特性静态传参动态传参
        参数数量固定:编译时确定可变:调用时可以变化
        方法定义参数数量和类型明确指定参数用 ... 形式声明,数量可变
        适用场景当参数数量固定时当参数数量不确定时
        调用方式需要按照方法定义传递确切的参数数量可以传递任意数量的同类型参数
        例子void method(int a, int b)void method(int... numbers)
      • Comparator 接口

        List<Integer> strings = Arrays.asList(1, 2, 3);
        
        Collections.sort(strings, new Comparator<Integer>) {
        @Override
        	public int compare (Integer o1, Integer o2) {
                return o1 - o2;
            }
        }
        
        Collections.sort(strings, (Integer o1, Integer o2) -> o1 - o2);
        
      • Listener接口

        JButton button = new JButton();
        button.addItemListener(new ItemListener() {
        @Override
        public void itemStateChanged(ItemEvent e) {
           e.getItem();
        }
        });
        //lambda
        button.addItemListener(e -> e.getItem());
        
      • 不难发现这些匿名内部类只重写了接口的一个方法,当然也只有一个方法要重写。这就是上文提到的函数式接口,也就是说只要方法的参数是函数式接口就可以用lambda表达式。

      • 自定义一个,java中的lambda就是减少实例化类这一步

        public class lambda {
        
            @FunctionalInterface
            public interface LambdaInterface {
                void f();
            }
        
            //使用
            public static class LambdaClass {
                public static void forEg() {
                    lambdaInterfaceDemo(() -> System.out.println("自定义函数式接口"));
                }
        
                //函数式接口参数
                static void lambdaInterfaceDemo(LambdaInterface i) {
                    i.f();
                }
            }
        
            public static void main(String[] args) {
                LambdaClass.forEg();
            }
        }
        
    2. 集合迭代

      void lamndaFor() {
              List<String> strings = Arrays.asList("1", "2", "3");
              //传统foreach
              for (String s : strings) {
                  System.out.println(s);
              }
              //Lambda foreach
              strings.forEach((s) -> System.out.println(s));
              //or
              strings.forEach(System.out::println);
           //map
              Map<Integer, String> map = new HashMap<>();
              map.forEach((k,v)->System.out.println(v));
      }
      
    3. 方法的引用

      • 静态方法的引用

        类名::静态方法

        package lambda;
        
        
        import java.util.Arrays;
        
        public class reference {
            public static void main(String[] args) {
                Student[] s = new Student[6];
                s[0] = new Student("张三", 18, "男", "北京");
                s[1] = new Student("李四", 19, "男", "上海");
                s[2] = new Student("王五", 20, "男", "广州");
                s[3] = new Student("赵六", 21, "男", "深圳");
                s[4] = new Student("孙七", 22, "男", "武汉");
                s[5] = new Student("周八", 23, "男", "西安");
                // lambda表达式,传入函数作为参数, 如果参数和调用的函数参数是一样的,才可以使用静态函数引用
                Arrays.sort(s, (o1, o2) -> o1.getAge() - o2.getAge());
        
                // 将类的静态方法作为引用,传送给函数式接口
                Arrays.sort(s, Student::compareByAge);
            }
        
        }
        
        package lambda;
        
        import lombok.AllArgsConstructor;
        import lombok.Data;
        import lombok.NoArgsConstructor;
        
        @Data
        @NoArgsConstructor
        @AllArgsConstructor
        public class Student {
            private String name;
            private int age;
            private String gender;
            private String address;
        
            public static int compareByAge(Student s1, Student s2)
            {
                return s1.getAge() - s2.getAge();
            }
        }
        

        实例方法

        package lambda;
        
        
        import java.util.Arrays;
        
        public class reference {
            public static void main(String[] args) {
                Student[] s = new Student[6];
                s[0] = new Student("张三", 18, "男", "北京");
                s[1] = new Student("李四", 19, "男", "上海");
                s[2] = new Student("王五", 20, "男", "广州");
                s[3] = new Student("赵六", 21, "男", "深圳");
                s[4] = new Student("孙七", 22, "男", "武汉");
                s[5] = new Student("周八", 23, "男", "西安");
                // lambda表达式,传入函数作为参数, 如果参数和调用的函数参数是一样的,才可以使用静态函数引用
                Arrays.sort(s, (o1, o2) -> o1.getAge() - o2.getAge());
        
                Student s1 = new Student();
                // 将类的静态方法作为引用,传送给函数式接口
                Arrays.sort(s, s1::compareByAge);
            }
        
        }
        

        特定类的调用

        public void Demo3 {
            public static void main(String[] args) {
                String[] names = {"Tom", "Cat", "Jerry"};
            }
            
            // Arrays.sort(names); // 默认按照首字母的升序排序
            // 忽略字母大小写升序  如果是特定类型的实例方法,以及是对应类方法
            // Arrays.sort(names, (o1, o2) -> o1.compareToIgnore(o2));
            Arrays.sort(names, String::compareToIgnore);
            
            System.out.println(Array.toString(names));
        }
        

        构造方法

        在这里插入图片描述

        class Car{
            String name;
            String getName() {
                return this.name;
            }
        }
        
        interface CarFactory {
            Car getCar(String name);
        }
        // CarFactory cf = new CarFactory {
        //	@override
        //	public Car getCar(String name);
        //		return new Car(name);
        //}
        // CarFactory cf = name -> new Car(name);
        
        
        CarFactory cf = Car::new;
        Car c1 = cd.getCar();
        
  • 这些方法是可遇不可求的,一般都是重构写出来的代码。

2.Interface

背景:

  1. 传统接口的缺点:

    • 一旦接口需要修改或增加方法,实现该接口的所有类都需要进行改动**。例如,假设 Animal 接口增加了一个新的方法 eat(),那么所有已经实现 Animal 接口的类 (DogCat 等) 都必须去实现这个新增加的方法,否则代码会报错。

    • 这给代码的维护和扩展带来了很大的问题,尤其当你有很多实现类时,修改接口将变得代价非常高昂。

  2. default修饰的方法,是普通的实例方法,可以用this调用,也可以被子类继承、重写。

  3. static修饰的方法,使用上和一般的类静态方法一样。但它不能被子类继承、重写。

  4. private修饰的方法,接口内部类才可以使用

​ 例子:

public interface InterfaceNew {
    static void sm() {
        System.out.println("interface提供的方式实现");
    }
    static void sm2() {
        System.out.println("interface提供的方式实现");
    }

    default void def() {
        System.out.println("interface default方法");
    }
    default void def2() {
        System.out.println("interface default2方法");
    }
    //须要实现类重写
    void f();
}

public interface InterfaceNew1 {
    default void def() {
        System.out.println("InterfaceNew1 default方法");
    }
}

因为两个接口没有继承关系,如果不重写def函数会编译出错

public class InterfaceNewImpl implements InterfaceNew , InterfaceNew1{
    public static void main(String[] args) {
        InterfaceNewImpl interfaceNew = new InterfaceNewImpl();
        interfaceNew.def();
    }

    @Override
    public void def() {
        InterfaceNew1.super.def();
    }

    @Override
    public void f() {
    }
}
  1. 抽象类和接口的区别
  • interface 和 class 的区别,好像是废话,主要有:

    • 接口多实现,类单继承
    • 接口的方法是 public abstract 修饰,变量是 public static final 修饰。 abstract class 可以用其他修饰符
  • interface 的方法是更像是一个扩展插件。而 abstract class 的方法是要继承的。

  1. functional interface接口
    • 也称SAM接口,既只有一个抽象方法的接口,在java8中有一个专门存放函数式接口的包java.util.function,该包下的所有接口都有@FunctionalInterface注解,提供函数式编程,提醒编译器,如果不是SAM接口解报错。

3.stream流

在这里插入图片描述

  • 实例

    package stream;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class demo1 {
        public static void main(String[] args) {
            // 目标:认证stream流
            List<String> list = new ArrayList<>();
            list.add("hello");
            list.add("world");
            list.add("java");
            list.add("hello");
            list.add("hello");
    
            // 1.常规方法
            List<String> newList = new ArrayList<>();
            for (String name : list) {
                if (name.startsWith("h") && name.length() != 1) {
                    newList.add(name);
                }
            }
    
            System.out.println(newList);
    
            // 2.stream流
            List<String> list2 =  list.stream().filter(name -> name.startsWith("h"))
                    .filter(name -> name.length() != 1)
                    .collect(Collectors.toList());
            System.out.println("------------------");
            System.out.println(list2);
        }
    }
    

在这里插入图片描述

3.1获取Stream流

  • Stream流是一个接口

    在这里插入图片描述

    package stream;
    
    import java.util.*;
    import java.util.stream.Stream;
    
    public class demo2 {
        public static void main(String[] args) {
            // 1.获取stream流
            // 获取集合里的stream流可以调用stream方法
            List<String> list = new ArrayList<>();
            Stream<String> s1 = list.stream();
    
            // 2.map
            Map<String, Integer> map = new HashMap<>();
            // 获取键流
            Stream<String> s2 = map.keySet().stream();
            // 获取值流
            Stream<Integer> s3 = map.values().stream();
            // 获取键值对流  entrySet把map转为set集合
            Stream<Map.Entry<String, Integer>> s4 = map.entrySet().stream();
    
            Set<Map.Entry<String, Integer>> test = new HashMap<String, Integer>().entrySet();
    
            // 3.数组 两种方式
            String[] arr = {"hello", "world", "java"};
            Stream<String> s5 = Arrays.stream(arr);
            System.out.println(s5.count());  // 计数
            System.out.println(s5.max(Comparator.comparingInt(String::length)));
            Stream<String> s6 = Stream.of("hello", "world", "java");
        }
    }
    

3.2处理stream流

在这里插入图片描述

  • 返回值是一个新流

    package stream;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.stream.Stream;
    
    public class demo3 {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("hello");
            list.add("world");
            list.add("java");
            list.add("hello");
    
            // 1.过滤方法    foreach将每个遍历出的元素塞给方法内。
            list.stream().filter(name -> name.startsWith("h") && name.length() != 1)
                    .forEach(System.out::println);
    
            // 2.排序方法
            List<Double> list1 = new ArrayList<>();
            list1.add(1.2);
            list1.add(2.3);
            list1.add(3.4);
            list1.add(1.2);
            // double可以排是因为里面实现了compare方法  默认是升序
            list1.stream().sorted().forEach(System.out::println);
            System.out.println("------------------");
            list1.stream().sorted((s1, s2) -> Double.compare(s2, s1)).forEach(System.out::println);
            // 只要前两名
            System.out.println("------------------");
            list1.stream().sorted().limit(2).forEach(System.out::println);
            // 跳过前两名
            System.out.println("------------------");
            list1.stream().sorted().skip(2).forEach(System.out::println);
            // 去重 如果需要自定义对象能够去重要重写hashCode和equals方法
            System.out.println("------------------");
            list.stream().distinct().forEach(System.out::println);
    
            // 映射方法, 把原来的数据拿出来加工并返回新流
            System.out.println("------------------");
            list1.stream().map(s -> s * 2).forEach(System.out::println);
    
            // 合并
            List<String> list2 = new ArrayList<>();
            list2.add("hello");
            list2.add("world");
            list2.add("java");
            Stream<String> list3 = list2.stream();
            Stream<String> list4 = list2.stream();
            Stream<String> s3 = Stream.concat(list4, list3);
            System.out.println(s3.count());
    
    
        }
    }
    
  • 如果需要自定义对象能够去重要重写hashCode和equals方法

  • 映射方法, 把原来的数据拿出来加工并返回新流

  • 都是一个个方法,记住就好,看源码收益低

3.3终结stream流

在这里插入图片描述

  • 抽象方法就是没实现的方法

    package stream;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Optional;
    
    public class demo4 {
        public static void main(String[] args) {
            // 创建一个教师列表并添加教师对象
            List<Teacher> teachers = new ArrayList<>();
            teachers.add(new Teacher("张三", 18, 3000));
            teachers.add(new Teacher("李四", 19, 4000));
            teachers.add(new Teacher("王五", 20, 5000));
            teachers.add(new Teacher("赵六", 21, 6000));
            teachers.add(new Teacher("钱七", 22, 7000));
    
            // 使用流的收集操作:
            // 过滤出工资大于4000的教师,并打印他们的信息
            teachers.stream()
                    .filter(teacher -> teacher.getSalary() > 4000) // 过滤条件
                    .forEach(System.out::println); // 打印符合条件的教师,自动调用toString方法
    
    
            // count
            long count = teachers.stream().filter(teacher -> teacher.getSalary() > 4000).count();
            System.out.println("~~~~~~~~~~~~~~");
    
            // 放到Optional<T>中防止空指针异常
            Optional<Teacher> max = teachers.stream().max(Teacher::compareTo);
            Teacher teacher = max.get();
            System.out.println(teacher.getName() + " " + teacher.getAge() + " " + teacher.getSalary());
    
        }
    }
    

在这里插入图片描述

  • 添加到集合中

    package stream;
    
    import java.util.*;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    public class demo4 {
        public static void main(String[] args) {
            // 收集到数组或者集合上
            List<String> test = new ArrayList<>();
            test.add("hello");
            test.add("world");
            Stream<String> s1 = test.stream().filter(s -> s.length() > 1);
            // 收集到List集合
            // Collectors.toList()返回一个ArrayList对象,明确调用了一个Collector的实现,明确使用ArrayList调用方法
            List<String> list = s1.collect(Collectors.toList());
            System.out.println(list);
            System.out.println("~~~~~~~~~~~~~~");
    
            // 收集到Set集合,流终止后不能再使用
            List<String> test2 = new ArrayList<>();
            test2.add("hello");
            test2.add("world");
            Set<String> set = test2.stream().filter(s -> s.length() > 1).collect(Collectors.toSet());
            System.out.println(set);
    
            // 收集到数组中 两个版本的toArray,参数是数组的构造器,默认返回的类型是Object[]
            Stream<String> s2 = test2.stream().filter(s -> s.length() > 1);
            String[] arr = s2.toArray(String[]::new);
            // Objects[] arr1 = s2.toArray();
            System.out.println(Arrays.toString(arr));
    
            // 收集到Map集合中,需要指定key和value的类型,否则会报错
            List<Teacher> list2 = new ArrayList<>();
            list2.add(new Teacher("张三", 18, 3000));
            list2.add(new Teacher("李四", 19, 4000));
            list2.add(new Teacher("王五", 20, 5000));
            list2.add(new Teacher("赵六", 21, 6000));
            list2.add(new Teacher("钱七", 22, 7000));
            Map<String, Integer> map = list2.stream().collect(Collectors.toMap(Teacher::getName, Teacher::getAge));
            System.out.println(map);
        }
    }
    
  • 在这里插入图片描述

  • 可以看到toList调用的是ArrayList

  • 每个方法都有默认的构造方法,按需调用即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2235462.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ubuntu双屏只显示一个屏幕另一个黑屏

简洁的结论&#xff1a; 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃&#xff0c;重新安装桌面安装不上&#xff0c;请IT帮忙&#xff0c;IT一番操作过后也表示…

Oracle OCP认证考试考点详解082系列15

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 71. 第71题&#xff1a; 题目 解析及答案&#xff1a; 对于数据库&#xff0c;使用数据库配置助手&#xff08;DBCA&#xff09;可以执行…

为什么说SQLynx是链接国产数据库的最佳选择?

第一是因为SQLynx提供了广泛的国产数据库支持&#xff0c;除了市面上的主流数据库MYSQL、Oracle、PostgreSQL 、SQL Server、SQLite、MongoDB外、还支持达梦人大金仓等国产数据源&#xff01; 近几年随着国产数据库市场的不断发展和成熟&#xff0c;越来越多的企业和机构开始选…

一个基于强大的 PostgreSQL 数据库构建的无代码数据库平台,快速构建应用程序,而无需编写一行代码(带私活源码)

随着企业和个人开发需求的不断增加&#xff0c;无代码平台成为了现代开发的重要组成部分&#xff0c;帮助那些没有技术背景的用户也能轻松创建和管理数据库应用程序。今天&#xff0c;我将向大家推荐一个非常出色的开源项目——Teable&#xff0c;它不仅支持无代码开发&#xf…

软件开发项目管理:实现目标的实用指南

由于软件项目多数是复杂且难以预测的&#xff0c;对软件开发生命周期的深入了解、合适的框架以及强大的工作管理平台是必不可少的。项目管理系统在软件开发中通常以监督为首要任务&#xff0c;但优秀的项目计划、管理框架和软件工具可以使整个团队受益。 软件开发项目管理的主要…

计算网络信号

题目描述&#xff1a; 网络信号经过传递会逐层衰减&#xff0c;且遇到阻隔物无法直接穿透&#xff0c;在此情况下需要计算某个位置的网络信号值。注意&#xff1a;网络信号可以绕过阻隔物 array[m][n]的二维数组代表网格地图&#xff0c; array[i][j]0代表i行j列是空旷位置&…

ESP8266 自定义固件烧录-Tcpsocket固件

一、固件介绍 固件为自定义开发的一个适配物联网项目的开源固件&#xff0c;支持网页配网、支持网页tcpsocket服务器配置、支持串口波特率设置。 方便、快捷、稳定&#xff01; 二、烧录说明 固件及工具打包下载地址&#xff1a; https://download.csdn.net/download/flyai…

数据结构与算法——Java实现 52.力扣98题——验证二叉搜索树

我将一直向前&#xff0c;带着你给我的淤青 —— 24.11.5 98. 验证二叉搜索树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的…

[mysql]DDL,DML综合案例,

综合案例 题目如下 目录 综合案例 ​编辑 ​编辑 # 1、创#1建数据库test01_library # 2、创建表 books&#xff0c;表结构如下&#xff1a; # 3、向books表中插入记录库存 # 4、将小说类型(novel)的书的价格都增加5。 # 5、将名称为EmmaT的书的价格改为40&#xff0c;并将…

书生实战营第四期-基础岛第三关-浦语提示词工程实践

一、基础任务 任务要求&#xff1a;利用对提示词的精确设计&#xff0c;引导语言模型正确回答出“strawberry”中有几个字母“r”。 1.提示词设计 你是字符计数专家&#xff0c;能够准确回答关于文本中特定字符数量的问题。 - 技能&#xff1a; - &#x1f4ca; 分析文本&…

国药准字生发产品有哪些?这几款不错

头秃不知道怎么选的朋友们看这&#xff0c;基本上市面上火的育发精华我都用了个遍了&#xff0c;陆陆续续也花了有大几w了&#xff0c;都是真金白银总结出来的&#xff0c;所以必须要给掉发人分享一些真正好用的育发产品&#xff0c;大家可以根据自己实际情况来选择。 1. 露卡菲…

构建基于 DCGM-Exporter, Node exporter,PROMETHEUS 和 GRAFANA 构建算力监控系统

目录 引言工具作用概述DCGM-ExporterNode exporterPROMETHEUSGRAFANA小结 部署单容器DCGM-ExporterNode exporterPROMETHEUSGRAFANANode exporterDCGM-Exporter 多容器Node exporterDCGM-ExporterDocker Compose 参考 引言 本文的是适用对象&#xff0c;是希望通过完全基于Doc…

Java入门14——动态绑定(含多态)

大家好&#xff0c;我们今天来学动态绑定和多态&#xff0c;话不多说&#xff0c;开始正题~ 但是要学动态绑定之前&#xff0c;我们要学习一下向上转型&#xff0c;方便后续更好地理解~ 一、向上转型 1.什么是向上转型 网上概念有很多&#xff0c;但其实通俗来讲&#xff0c…

Request 和 Response 万字详解

文章目录 1.Request和Response的概述2.Request对象2.1 Request 继承体系2.2 Request获取请求数据2.2.1 获取请求行数据2.2.2 获取请求头数据2.2.3 获取请求体数据2.2.4 获取请求参数的通用方式 2.3 解决post请求乱码问题 掌握内容讲解内容小结 2.4 Request请求转发 3.HTTP响应详…

Qt QCustomplot 在采集信号领域的应用

文章目录 一、常用的几种开源库:1、QCustomPlot:2、QChart:3、Qwt:QCustomplot 在采集信号领域的应用1、应用实例时域分析频谱分析2.数据筛选和处理其他参考自然界中的物理过程、传感器和传感器网络、电路和电子设备、通信系统等都是模拟信号的来源。通过可视化模拟信号,可以…

【初阶数据结构与算法】沉浸式刷题之顺序表练习(顺序表以及双指针两种方法)

文章目录 顺序表练习1.移除数组中指定的元素方法1&#xff08;顺序表&#xff09;方法2&#xff08;双指针&#xff09; 2.删除有序数组中的重复项方法1&#xff08;顺序表&#xff09;方法2&#xff08;双指针&#xff09; 3.双指针练习之合并两个有序数组方法1&#xff08;直…

机器学习—矩阵乘法

矩阵只是一个或两个数组。 如何在向量之间取点积&#xff1f; 让我们用列向量[1,2]*[[3,4]&#xff0c;如果z是这两个向量之间的点积&#xff0c;然后通过乘以第一个元素来计算z&#xff0c;通过这里的第一个元素&#xff0c;所以是1*3加第二个元素乘以第二个元素即2*4&#…

使用 ADB 在某个特定时间点点击 Android 设备上的某个按钮

前提条件 安装 ADB&#xff1a;确保你已经在计算机上安装了 Android SDK&#xff08;或单独的 ADB&#xff09;。并将其添加到系统环境变量中&#xff0c;以便你可以在命令行中运行 adb。 USB调试&#xff1a;确保 Android 设备已启用 USB 调试模式。这可以在设备的“设置” -…

数据结构之二叉树前序,中序,后序习题分析(递归图)

1.比较相同的树 二叉树不能轻易用断言&#xff0c;因为树一定有空 2.找结点值 3.单值二叉树 4.对称二叉树 5.前序遍历

[CUDA] 将已有的地址空间设置为pinned memory

文章目录 1. cudaHostRegitster的使用构建pinned memory1.1 基本使用1.2 cudaHostRegister 需要设置cudaSetDevice? Reference 1. cudaHostRegitster的使用构建pinned memory 注意使用C申请的内存空间&#xff0c;在进行copy是无法实现流的最大异步性&#xff1b;因此使用cud…