JDK8新特性

《Lambda表达式》

一、为什么要使用Lambda表达式

  • 避免匿名内部类定义过多
  • 让代码看起来简洁
  • 去掉多余没有意义的代码
  • 留下核心逻辑
  • Lambda是在JDK1.8中产生的

二、理解Functional Interface(函数式接口)

  • 函数式接口是学习Java8 lambda表达式的关键所在

  • 函数式接口定义:

    • 任何接口,如果只包含唯一一个抽象方法,那么他就是一个函数式接口
    public interface Runnable{
        public abstract void run();
        //接口中默认方法为抽象方法,也可以不写abstract修饰符
    }
    
    • 对于函数式接口,我们可以通过lambda表达式来创建该接口的对象

Lambda演变史

(1)正常操作


public class TestLambdaImpl implements TestLambda{

    @Override
    public void lambda() {
        System.out.println("I like Lambda");
    }

    public static void main(String[] args) {
        TestLambdaImpl testLambda = new TestLambdaImpl();
        testLambda.lambda();
    }
}
interface TestLambda{
    void lambda();
}

(2)静态内部类


public class TestLambdaImpl{

    static class Test01Impl implements TestLambda{

        @Override
        public void lambda() {
            System.out.println("静态内部类");
        }
    }
    public static void main(String[] args) {
        Test01Impl ti = new Test01Impl();
        ti.lambda();
    }
}
interface TestLambda{
    void lambda();
}

(3)局部类

public class TestLambdaImpl{

    public static void main(String[] args) {
        class Test01Impl implements TestLambda{

            @Override
            public void lambda() {
                System.out.println("局部类");
            }
        }
        Test01Impl ti = new Test01Impl();
        ti.lambda();
    }
}
interface TestLambda{
    void lambda();
}

(4)匿名内部类

没有类的名称,必须借助接口或者父类

public class TestLambdaImpl{
    public static void main(String[] args) {
        TestLambda testLambda = null;
        testLambda= new TestLambda(){
            @Override
            public void lambda() {
                System.out.println("匿名内部类");
            }
        };
        testLambda.lambda();
    }
}
interface TestLambda{
    void lambda();
}

(5)Lambda表达式

public class TestLambdaImpl{
    public static void main(String[] args) {
        TestLambda testLambda = null;
        testLambda = ()->{
            System.out.println("Lambda表达式");
        };
        //也可以写成 "testLambda = ()->System.out.println("Lambda表达式");"

        testLambda.lambda();
    }
}
interface TestLambda{
    void lambda();
}

《StreamAPI》

Stream流主要用在操作集合上,例如:

简单概述

  • Stream就是操作容器的

实例化
方式一:

/**
* 通过集合获取Stream
*/
@Test
public void test01(){
    List<Student> students = StudentData.getStudents();

    Stream<Student> stream = null;

    //返回顺序流
    stream = students.stream();

    //返回并行流
    stream = students.parallelStream();
    System.out.println(stream);
}

方式二:

/**
 * 通过数组创建
 */
@Test
public void test02(){
    int[] arr = new int[]{1,2,3,4,5,6};
    IntStream stream = Arrays.stream(arr);

    Student student01 = new Student(1002, "李四", 21, 65.0);
    Student student02 = new Student(1003, "王五", 22, 75.0);
    
    Student[] arr01 = new Student[]{student01,student02};
    Stream<Student> stream1 = Arrays.stream(arr01);
}

方式三:

/**
 * 通过Stream的of
 */
@Test
public void test03(){
    Stream<String> stringStream = Stream.of("1", "2", "3");
}

中间操作

01.筛选与切片

  • filter(Predicate p):接收Lambda,从流中排除某些元素

        @Test
        public void test01(){
            List<Student> students = StudentData.getStudents();
            //查询学生表中成绩大于70的
            students.stream().filter(student -> student.getScope() > 70).forEach(System.out::println);
        }
    
  • distinct():筛选,通过流所生成的hashCode()和equals()去除重复元素

    //去重(取出对象中所有数据均相同的数据)
            StudentData.getStudents().stream().distinct().forEach(System.out::println);
    
  • limit(long maxSize):截断流,使其元素不超过给定数量

    //截断流,获取前三个
    StudentData.getStudents().stream().limit(3).forEach(System.out::println);
    
  • skip(long n):跳过元素,返回一个扔掉前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补

    //跳过前三个,获取其他的
    StudentData.getStudents().stream().skip(3).forEach(System.out::println);
    

02.排序

  • sorted:产生一个新流,其中按自然顺序排序

    //自然排序
    List<Integer> integers = Arrays.asList(1, 200, 34, 4, 556, 61);
    integers.stream().sorted().forEach(System.out::println);
    
  • sorted:产生一个新流,其中按比较器顺序排序

    //定制排序(根据年龄排序)
    List<Student> students = StudentData.getStudents();
    students.stream().sorted((e1,e2) -> Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println);
    

03.映射

将字母变成大写

List<String> strings = Arrays.asList("aa", "bb", "cc", "dd");
strings.stream().map(str->str.toUpperCase()).forEach(System.out::println);

获取学生姓名大于3的姓名

StudentData.getStudents().stream().map(Student::getName).collect(Collectors.toList()).stream().filter(student01 -> student01.length()>3).forEach(System.out::println);

04.终止操作

import java.util.Optional;

public class StreamAPITest02 {
    @Test
    public void test01(){
        /*
        allMatch(Predicate p) 检查是否匹配所有元素
        查询是否年龄均大于18
         */
        boolean allMatch = StudentData.getStudents().stream().allMatch(e -> e.getAge() > 18);
        System.out.println(allMatch);
        System.out.println();

        /*
        anyMatch(Predicate p) 检查是否至少匹配一个元素
        查询是成绩是否有75分的
        */
        boolean anyMatch = StudentData.getStudents().stream().anyMatch(e -> e.getScope()==65);
        System.out.println(anyMatch);
        System.out.println();

        /*
        noneMatch(Predicate p) 检查是否没有匹配的元素
        查询是是否存在学生姓李

        若存在则返回false,不存在返回true
        */
        boolean noneMatch = StudentData.getStudents().stream().noneMatch(e -> e.getName().contains("李"));
        System.out.println(noneMatch);
        System.out.println();

        /*
        findFirst:返回第一个元素
         */
        Optional<Student> first = StudentData.getStudents().stream().findFirst();
        System.out.println(first);
        System.out.println();

        /*
        count:返回流中的个数
         */
        long count = StudentData.getStudents().stream().count();
        System.out.println(count);
        System.out.println();

        /*
        max:返回流中最大值
         */
        Optional<Double> max = StudentData.getStudents().stream().map(e -> e.getScope()).max(Double::compareTo);
        System.out.println(max.get());
        System.out.println();

        /*
        min:返回流中最小值
         */
        Optional<String> s = StudentData.getStudents().stream().min((e1, e2) -> Double.compare(e1.getScope(), e2.getScope())).map(Student::getName);
        System.out.println(s.get());
    }
}

归约

  • reduce(T iden,BinaryOperator* b*):可以将流中元素反复结合起来,得到一个值。返回T

    /*
    计算1-10的和
    */
    List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    System.out.println(integers.stream().reduce(0, Integer::sum).intValue());
    
    /*
    计算所有学生总成绩
    */
    Double reduce = StudentData.getStudents().stream().map(e -> e.getScope()).reduce((double) 0, Double::sum);
    System.out.println(reduce);
    
  • reduce(BinaryOperator b):可以将六种元素反复结合起来,得到一个值。返回Optional<T>

    /*
    计算总成绩
    */
    Optional<Double> reduce = StudentData.getStudents().stream().map(Student::getScope).reduce(Double::sum);
    System.out.println(reduce);
    

收集

  • Collector:收集为List集合或者Set集合

    /*
    查找成绩大于80的同学,返回结果一个List或set
    */
    
    //返回List
    List<Student> collect = StudentData.getStudents().stream().filter(student -> student.getScope() > 80).collect(Collectors.toList());
    collect.forEach(System.out::println);
    System.out.println();
    
    //返回Set
    Set<Student> collect1 = StudentData.getStudents().stream().filter(student -> student.getScope() > 80).collect(Collectors.toSet());
    collect1.forEach(System.out::println);
    

《TimeAPI》

在之前版本中,日期时间设计考虑不周。主要是非线程安全、时区处理麻烦

新版Java中,引入了如下API:

LocalDate:表示日期,包含:年月日。格式为:2020-01-13
LocalTime:表示时间,包含:时分秒。格式为:16:39:09.307
LocalDateTime:表示日期时间,包含:年月日 时分秒。格式为:2020-01-13T16:40:59.138
DateTimeFormatter:日期时间格式化类
Instant:时间戳类
Duration:用于计算 2 个时间(LocalTime,时分秒)之间的差距
Period:用于计算 2 个日期(LocalDate,年月日)之间的差距
ZonedDateTime:包含时区的时间

《接口增强》

在JDK8之前,JDK规定接口中只能定义 ①静态常量 ②抽象方法

修饰词 interface 接口名{
    静态常量;
    抽象方法;
}

在JDK8之后,对接口进行了增强。我们可以在接口中定义 ①静态常量 ②抽象方法 ③默认方法④静态方法

修饰词 interface 接口名{
    静态常量;
    抽象方法;
    默认方法;
    静态方法;
}

《重复注解》

在 Java 8 之前我们不能在同一个类、同一方法上重复使用同一个注解

@PropertySource("classpath:config1.properties")
@PropertySource("classpath:config2.properties")
public class AnnotationDemo{
	//代码部分
}

上面的代码无法在 Java 7 下通过编译,错误是: Duplicate annotation。在 JDK 8 中引入了一个注解 @Repeatable 来标识某个注解是可被重复使用的,但是需要一个容器注解。可重复注解的使用步骤如下:

1.1定义可重复的注解容器注解

@Retention(RetentionPolicy.RUNTIME)
@interface MyTests {//这是重复的容器注解
    MyTest[] value();
}

1.2定义一个可以重复的注解

@Retention(RetentionPolicy.RUNTIME)
@Repeatable(MyTests.class)
@interface MyTest{
    String value();
}

1.3配置多个重复的注解

@MyTest("mt1")
@MyTest("mt2")
@MyTest("mt3")
public class annotationDemo {

    @Test
    @MyTest("ms1")
    @MyTest("ms2")
    public void test(){

    }

    @Test
    @MyTest("mn1")
    @MyTest("mn2")
    public void test(String name){

    }
}

1.4解析配置的重复注解

@MyTest("mt1")
@MyTest("mt2")
@MyTest("mt3")
public class annotationDemo {

    @Test
    @MyTest("ms1")
    @MyTest("ms2")
    public void test(){

    }

    @Test
    @MyTest("mn1")
    @MyTest("mn2")
    public void test(String name){

    }

	//4.解析配置的重复注解
    public static void main(String[] args) throws NoSuchMethodException {
        //4.1 获取类上的注解
        //getAnnotationsByType() 是新增的API,用于用户获取重复的注解
        MyTest[] annotationsByType = annotationDemo.class.getAnnotationsByType(MyTest.class);
        for (MyTest myTest: annotationsByType) {
            System.out.println("获取类上的注解:"+myTest.value());
        }

        //4.2 获取(无参方法)方法上的注解
        //getAnnotationsByType() 是新增的API,用于用户获取重复的注解
        MyTest[] tests = annotationDemo.class.getMethod("test", null).getAnnotationsByType(MyTest.class);
        for (MyTest myTest: tests) {
            System.out.println("获取(无参方法)方法上的注解:"+myTest.value());
        }

        //4.2 获取(有参方法)方法上的注解
        //getAnnotationsByType() 是新增的API,用于用户获取重复的注解
        MyTest[] tests1 = annotationDemo.class.getMethod("test", String.class).getAnnotationsByType(MyTest.class);
        for (MyTest myTest: tests1) {
            System.out.println("获取(有参方法)方法上的注解:"+myTest.value());
        }
    }
}

参考文章

[1.]JDK8新特性-扛麻袋的少年

posted @   DAawson  阅读(84)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示