Java8新特性

Java8的新特性

一、概述

  • Java8 (又称JKD1.8)是Java语言开发的一个主要版本。
  • Oracle公司于2014年3月18日发布Java8
    • 支持Lambda表达式
    • 函数式接口
    • 新的Stream API
    • 新的日期API
    • 其他特性

二、Lambda表达式

  • Lambda表达式:特殊的匿名内部类,语法更简洁

  • Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递) ,将代码像数据一样传递

  • Lambda表达式:在Java 8语言中引入的一种新的语法元素和操作符。这个操作符为-> , 该操作符被称为Lambda操作符或箭头操作符。它将Lambda分为两个部分:

  • 左侧:指定了Lambda表达式需要的参数列表(其实就是接口中的抽象方法的形参列表);
  • 右侧:指定了Lambda体,是抽象方法的实现逻辑,也即Lambda表达式要执行的功能(其实就是重写的抽象方法的方法体)。
  • 语法格式1:无参,无返回值
Runable r = () -> {System.out.println("hello world");}
  • 语法格式2:Lambda需要一个参数,但是没有返回值
Consumer<String> con = (String str) -> {System.out.println(str);}
  • 语法格式3:数据类型可以省略,因为可由编译器推断得出,称为类型推断
Consumer<String> con = (str) -> {System.out.println(str);}
  • 语法格式4:Lambda若只需要一个参数时,参数的小括号可以省略
Consumer<String> con = str -> {System.out.println(str);}
  • 语法格式5:Lambda需要两个或以上的参数,多条执行语句,并且可以有返回值

  • 注意事项:

    • 形参列表的数据类型会自动推断
    • 如果形参列表为空,只需保留()
    • 如果形参只有1个,()可以省略,只需要参数的名称即可
    • 如果执行语句只有一-句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句
    • Lambda不会生成一个单独的内部类文件
//学生类
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Demo01 {
    public static void main(String[] args) {
        test03();
    }
    /*
    * Lambda表达式的语法:
    *   ()->{}
    *   ()表示方法的参数、
    *   ->
    *   {}表示方法的实现
    * */

    //启动线程
    public  static void test01(){
        //使用匿名内部类实现
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类启动线程");
            }
        }).start();

        //使用Lambda表达式实现
        new Thread(()-> System.out.println("使用lambda表达式启动线程...")).start();
    }


    public static void test02(){
        //定义一个集合对集合进行排序
        ArrayList<Student> students = new ArrayList<>();
        students.add(new Student("aaa",15));
        students.add(new Student("bbb",16));
        students.add(new Student("ccc",17));
        //使用匿名内部类实现
        Collections.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getAge()-o1.getAge();
            }
        });

        //使用Lambda表达式实现
        Collections.sort(students,((o1,o2)->o2.getAge()-o1.getAge()));

        for (Student stu : students) {
            System.out.println(stu);
        }
    }

    public static void test03(){
        //扫描D盘下的java文件
        File file = new File("D:\\Folder");
        //使用内名内部类进行扫描
/*
      File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".java");
            }
        });
*/
        //使用Lambda表达式实现
        File[] files1 = file.listFiles(pathname -> pathname.getName().endsWith(".java"));

        for (File f : files1) {
            System.out.println(f);
        }
    }
}

三、函数式接口

如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上

  • @FunctionalInterface注解检测接口是否符合函数式接口
public class Demo01 {
    public static void main(String[] args) {
        //使用匿名内部类
        test01(new MyFunctionalInterface() {
            @Override
            public void Show() {
                System.out.println("匿名内部类实现");
            }
        });

        //Lambda表达式实现
        test01(()-> System.out.println("Lambda表达式实现"));
    }
    public static void test01(MyFunctionalInterface m1){
        m1.Show();
    }
    @FunctionalInterface
    interface MyFunctionalInterface{
        void Show();
    }
}

3.2java常用内置函数式接口

函数式接口参数类型返回值类型用途
Consumer<T>消费型接口Tvoidvoid accept(T t);对类型为T的对象应用操作
Supplier<T>供给型接口TT get(); 返回类型为T的对象
Function<T,R>函数型接口TRR apply(T t);对类型为T的对象应用操作,并返回类型为R类型的对象。
Predicate<T>断言型接口Tbooleanboolean test(T t);确定类型为T的对象是否满足条件,并返回boolean类型。

Consumer<T>消费型接口

import java.util.function.Consumer;

public class Demo02 {
    //Consumer<T>消费型接口
    //定义一个方法传入一个字符串输出字符串长度
    public static void test01(String str, Consumer<String> consumer){
        consumer.accept(str);
    }

    public static void main(String[] args) {
        //使用匿名内部类实现
        test01("hello,java", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s.length());
            }
        });

        //使用Lambda表达式
        test01("hello,java",t-> System.out.println(t.length()));
    }
}

Supplier<T>供给型接口

import java.util.function.Supplier;

public class Demo03 {
    //定义一个方法 返回100以内最大的质数
    public  static  int test01(Supplier<Integer> supplier){
        return supplier.get();
    }


    public static void main(String[] args) {
//        test01(new Supplier<Integer>() {
//            @Override
//            public Integer get() {
//                for (int i = 100; i >=2 ; i--) {
//                    boolean flag=true;
//                    for (int j = 2; j <i ; j++) {
//                        if (i%j==0){
//                            flag=false;
//                            break;
//                        }
//                    }
//                    if (flag){
//                        return i;
//                    }
//                }
//                return 2;
//            }
//        });

        //使用Lambda表达式
        int num=test01(()->{
            for (int i = 100; i >=2 ; i--) {
                boolean flag=true;
                for (int j = 2; j <i ; j++) {
                    if (i%j==0){
                        flag=false;
                        break;
                    }
                }
                if (flag){
                    return i;
                }
            }
            return 2;
        });
        System.out.println(num);
    }
}

Function<T,R>函数型接口

import java.util.function.Function;

public class Demo04 {

    //传入一个数组  返回指定的数组的和
    public  static  int  test01(int[] arr, Function<int[],Integer> function){
        return function.apply(arr);
    }

    public static void main(String[] args) {
        int[] arr={1,2,3,4,5};
//        int sum=test01(arr, new Function<int[], Integer>() {
//            @Override
//            public Integer apply(int[] ints) {
//                int sum=0;
//                for (int i = 0; i <arr.length ; i++) {
//                    sum+=ints[i];
//                }
//                return sum;
//            }
//        });

        //使用Lambda表达式
        int sum=test01(arr,a->{
            int sum1=0;
            for (int i = 0; i <arr.length ; i++) {
                sum1+=a[i];
            }
            return sum1;
        });
        System.out.println(sum);
    }
}

Predicate<T>断言型接口

import java.util.function.Predicate;

public class Demo05 {
    //传入一个数  判断是否为3的倍数
    public static  boolean test01(int num, Predicate<Integer> predicate){
        return  predicate.test(num);
    }

    public static void main(String[] args) {
//        boolean b=test01(15, new Predicate<Integer>() {
//            @Override
//            public boolean test(Integer integer) {
//                return integer%3==0;
//            }
//        });

        boolean b = test01(14, t -> t % 3 == 0);

        System.out.println(b);
    }
}

四、方法引用与构造器引用

4.1方法引用

  • 方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体中
  • 只是调用一个特定的已经存在的方法,则可以使用方法引用。
  • 常见形式
    • 对象::实例方法
    • 类::静态方法
    • 类::实例方法
    • 类::new
import java.util.Locale;
import java.util.Random;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class Demo01 {
    public static void main(String[] args) {
/*        test01("aaa", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
 */

/*        //使用Lambda表达式
        test01("aaa",name-> System.out.println(name));

        //使用方法引用
        test01("bbb", System.out::println);//一个属性 一段逻辑代码
*/

/*
        //传入一个字符串 变为大写返回这个字符串的大写
        //使用Lambda表达式
        test02("hello",s->s.toUpperCase());
        //使用方法引用
        test02("aaa",String::toUpperCase);
*/

    test03(Math::random);

    test04("aaa", Person::new);

    }
    public static void test01(String name, Consumer<String> consumer){
        consumer.accept(name);
    }

    //传入一个字符串 变为大写返回这个字符串的大写
    public static void test02(String str , Function<String,String> function){
        System.out.println(function.apply(str));
    }

    //使用Random返回随机数
    public static void test03(Supplier<Double> supplier){
        System.out.println(supplier.get());
    }

    //传入name属性返回person对象
    public static void test04(String name,Function<String,Person> function){
        System.out.println(function.apply(name));

    }
}
class Person{
    String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}

五、Stream API

5.1概述

  • 流(Stream) 与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作

  • Stream自己不会存储元素

  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream

  • Stream操作是延迟执行的,会等到需要结果的时候才执行

5.2Stream操作的三个步骤

  1. 创建 Stream
    • 一个数据源(如:集合、数组),获取一个流
  2. 中间操作
    • 产生一个中间操作链,对数据源的数据进行处理
  3. 终止操作(终端操作)
    • 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Demo01 {
    public static void main(String[] args) {
        test03();
    }
    //如何创建Stream流对象
    public static void test01(){
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        Stream<String> stream = list.stream();
 /*
        stream.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
 */

        //使用Lambda表达式
        stream.forEach(t-> System.out.println(t));
        //通过方法引用
        stream.forEach(System.out::println);

        int[] arr = {1,2,3,4,5,6,7};
        IntStream stream1 = Arrays.stream(arr);
        stream1.forEach(System.out::println);
    }

    public static void test02(){
        //流的中间操作
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        list.add("eee");
        Stream<String> stream = list.stream();

        //filter过滤集合元素长度大于4的
        list.stream().filter(t->t.length( )>4).forEach(System. out::println);

        //limit 限定查询前两个
        list.stream().limit(2).forEach(System. out::println);

        //skip跳过查询
        list.stream().skip(2).forEach(System. out::println);

        //分页查询
        //第一页
        list.stream().limit(2).forEach(System. out::println);
        //第二页
        list.stream().skip(2).limit(2).forEach(System. out::println);

        //去重查询
        list.stream().distinct().forEach(System. out::println);

        //排序查询
        list.stream().sorted(((o1, o2) -> o2.length()-o1.length())).forEach(System. out::println);

        //map将元素进行重新映射
        list.stream().map(li->"姓名为:"+li).forEach(System.out::println);

        list.stream().forEach(li->System.out.println(Thread.currentThread().getName()+"---"+li));
        list.stream().parallel().forEach(li->System.out.println(Thread.currentThread().getName()+"---"+li));
    }
    public static void test03() {
        //流的终止操作
        ArrayList<String> list = new ArrayList<>();
        list.add("9");
        list.add("5");
        list.add("2");
        list.add("7");

        list.stream().forEach(System.out::println);

/*
        //获取最大值
        Optional<Integer> max = list.stream().map(Integer::parseInt).max((o1, o2) -> o1 - o2);
        System.out.println(max.get());

        //获取最小值
        Optional<Integer> min = list.stream().map(Integer::parseInt).min((o1, o2) -> o1 - o2);
        System.out.println(min.get());
*/

        //获取个数
        long count = list.stream().map(Integer::parseInt).filter(li -> li >=1).count();
        System.out.println(count);

        //reduce 计算
        Optional<Integer> reduce = list.stream().map(Integer::parseInt).reduce((o1, o2) -> o1 + o2);
        Optional<Integer> reduce1 = list.stream().map(Integer::parseInt).reduce(Integer::sum);
        System.out.println(reduce1.get());

        List<Integer> list1 = list.stream().map(Integer::parseInt).filter(li -> li > 5).collect(Collectors.toList());
        list1.stream().forEach(System.out::println);
    }
}

六、新时间API

  • 之前时间API存在问题:线程安全问题、设计混乱
  • 本地化日期时间APlI:
    • LocalDate
    • LocalTime
    • LocalDateTime
    • Instant: 时间戳
    • Zoneld: 时区。
    • Date、Instant、LocalDate Time的转换。
    • DateTimeFormatter: 格式化类。
import javax.swing.text.DateFormatter;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Demo {
    public static void main(String[] args) {
        test05();
    }
    //获取日期对象
    public static void test01(){
        LocalDate date = LocalDate.now();//当前系统日期
        LocalTime time = LocalTime.now();//当前系统时间
        LocalDateTime localDateTime = LocalDateTime.now();//系统时间+日期
        System.out.println(date);
        System.out.println(time);
        System.out.println(localDateTime);
    }

    //获取日期对象的年 月 日 时 分 秒
    public static void test02(){
        LocalDateTime dateTime = LocalDateTime.now();
        System.out.println(dateTime.getYear());
        System.out.println(dateTime.getMonthValue());
        System.out.println(dateTime.getDayOfMonth());
        System.out.println(dateTime.getHour());
        System.out.println(dateTime.getMinute());
        System.out.println(dateTime.getSecond());
    }

    //设置日期对象的信息 年 月 日 时 分 秒
    public static void test03(){
        LocalDateTime dateTime = LocalDateTime.now();
        dateTime = dateTime.withMonth(12).withDayOfMonth(25).withYear(2025);
        System.out.println(dateTime.getYear());
        System.out.println(dateTime.getMonthValue());
        System.out.println(dateTime.getDayOfMonth());
    }

    //加减日期对象信息
    public static void test04(){
        LocalDateTime dateTime = LocalDateTime.now();
        dateTime = dateTime.plusMonths(15).minusDays(2);
        System.out.println(dateTime.getYear());
        System.out.println(dateTime.getMonthValue());
        System.out.println(dateTime.getDayOfMonth());
    }

    //
    public static void test05(){

        //将日期格式转换成字符串
//        LocalDateTime dateTime = LocalDateTime.now();
//
//        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//
//        String format = dateTimeFormatter.format(dateTime);
//
//        System.out.println(format);
//
        //将字符串解析成日期
        String time="2022-12-25 10:10:10";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(time, dateTimeFormatter);
        System.out.println(localDateTime);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值