Java8新特性/java

news/2024/11/8 20:23:19 标签: java, 开发语言

1.lambda表达式

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

  • 语法格式

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

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

      • Runnable接口

        java">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 接口

        java">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接口

        java">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就是减少实例化类这一步

        java">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. 集合迭代

      java">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. 方法的引用

      • 静态方法的引用

        类名::静态方法

        java">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);
            }
        
        }
        
        java">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();
            }
        }
        

        实例方法

        java">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);
            }
        
        }
        

        特定类的调用

        java">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));
        }
        

        构造方法

        在这里插入图片描述

        java">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修饰的方法,接口内部类才可以使用

​ 例子:

java">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流

在这里插入图片描述

  • 实例

    java">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流是一个接口

    在这里插入图片描述

    java">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流

在这里插入图片描述

  • 返回值是一个新流

    java">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流

在这里插入图片描述

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

    java">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());
    
        }
    }
    

在这里插入图片描述

  • 添加到集合中

    java">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.niftyadmin.cn/n/5744389.html

相关文章

【论文阅读】火星语义分割的半监督学习

【论文阅读】火星语义分割的半监督学习 文章目录 【论文阅读】火星语义分割的半监督学习一、介绍二、联系工作3.1Deep Learning for Mars3.2 数据集可以分为三类&#xff1a;3.3 半监督学习 三、提出的火星图像分割数据集四、方法四、实验 S 5Mars: Semi-Supervised Learning …

【ArcGISPro】单次将自己建立的工具箱添加至Arcpy中

新建工具箱 添加至Arcpy中 调用刚添加的工具箱

将vscode的终端改为cygwin terminal

现在终端是默认的power shell&#xff0c;没有显示cygwin 接下来选择默认配置文件 找到cygwin的选项即可 然后提示可能不安全什么的&#xff0c;点是&#xff0c;就有了

智能量化投资:中阳模型的多维创新与前景

一、中阳智能模型在量化投资中的优势 在日益复杂的金融市场环境中&#xff0c;量化投资正逐步引领金融科技的潮流。中阳智能模型以其创新的数据处理和分析能力脱颖而出&#xff0c;依托先进的算法及大数据分析&#xff0c;建立起动态、精准的投资策略。这一模型的优势不仅表现…

PHP露营地管理平台小程序系统源码

⛺️【露营新风尚】露营地管理平台系统全攻略⛺️ &#x1f3d5;️一、露营热潮下的管理难题&#xff1a;如何高效运营露营地&#xff1f;&#x1f914; 随着露营文化的兴起&#xff0c;越来越多的人选择在大自然中享受宁静与自由。然而&#xff0c;露营地的管理却面临着诸多…

基于STM32的实时时钟(RTC)教学

引言 实时时钟&#xff08;RTC&#xff09;是微控制器中的一种重要功能&#xff0c;能够持续跟踪当前时间和日期。在许多应用中&#xff0c;RTC用于记录时间戳、定时操作等。本文将指导您如何使用STM32开发板实现RTC功能&#xff0c;通过示例代码实现当前时间的读取和显示。 环…

ES文档:文档操作_doc(7.9.2)

用心记录技术&#xff0c;走心分享&#xff0c;始于后端&#xff0c;不止于后端&#xff0c;励志成为一名优秀的全栈架构师&#xff0c;真正的实现码中致富。 ElasticSearch文档的操作&#xff1b; 添加文档 新建一个索引 goboy-blog&#xff0c;如果添加文档索引不存在则会创…

【Python】图片处理

一、获取图片尺寸 优点缺点Pillow功能丰富&#xff0c;支持多种图像处理操作。使用简单&#xff0c;适合快速原型开发。对于处理大型图像或批量图像时&#xff0c;性能可能不如OpenCV。OpenCV性能强大&#xff0c;适合处理大型图像和视频处理。提供了丰富的计算机视觉算法。相…