jdk8的新特性

1. lambda表达式

概念:
        Lambda表达式:特殊的匿名内部类,语法更简洁。
        Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

语法:

<函数式接口> <变量名> = (参数1,参数2...) -> {

        //方法体

};

注意:函数式接口:如果一个接口只有一个抽象方法,则该接口称之为函数式接口。
           (参数1,参数2):抽象方法的参数,形参列表的数据类型会自动推断;如果形参列表为空,只需要保留();如果形参只有1个,()可以省略,只需要参数的名称即可。
           -> : 分隔符,Lambda引入了新的操作符。
          {} : 表示抽象方法的实现(方法体),如果执行语句只有一句,且无返回值,{}可以省略;若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句。

package demo01;

public class Test01 {
    public static void main(String[] args) {
        Runnable runnable = () ->{
            System.out.println("这是lambda表达式方式创建的任务方法对象");
        };
        Thread t1 = new Thread(runnable);
        t1.start();
    }
}

Lambda表达式的作用:简化匿名内部类的使用,语法更加简单。

2. 函数式接口

如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。
@FunctionalInterface  注解检测接口是否符合函数式接口。

常见的函数式接口
       
由于Lambda使用时不关心接口名,抽象方法名,只关心抽象方法的参数列表和返回值类型。因此JDK提供了大量常用的函数式接口。java.util.function

2.1 Consumer<T>

        有参数,无返回值。

package demo03;

import java.util.function.Consumer;

public class Test03 {

    public static void main(String[] args) {
        fun(arr -> {
            int sum=0;
            for(int n:arr){
                sum+=n;
            }
            System.out.println("数组的和为:"+sum);
        });
    }

    public static void fun(Consumer<int[]> consumer){
         int[] arr={1,3,5,7,8,10};
         consumer.accept(arr);
    }

}

2.2 Supplier<T>供给型函数式接口

        T:表示返回结果的泛型    无参,有返回结果的函数式接口时。

package demo04;

import java.util.Random;
import java.util.function.Supplier;

public class Test04 {
    public static void main(String[] args) {
        fun(()->{
            return new Random().nextInt(10);
        });
    }
    public static void fun(Supplier<Integer> supplier){
        Integer integer = supplier.get();
        System.out.println("内容:"+integer);
    }
}

2.3 Function<T,R>   函数型函数式接口

        T:参数类型的泛型
        R:函数返回结果的泛型
        有参,有返回值时。

package demo05;

import java.util.function.Function;

public class Test05 {
    public static void main(String[] args) {
        fun((t)->{
            return t.toUpperCase();
        },"hello world");
    }
    public static void fun(Function<String,String> function,String msg){
        String s = function.apply(msg);
        System.out.println("字符串小写转大写后:"+s);
    }
}

 2.4 Predicated<T>

        T: 参数的泛型   返回一个boolean值
        当传入一个参数时,需要对该参数进行判断时,则需要这种函数。

package demo06;

import java.util.function.Predicate;

public class Test06 {
    public static void main(String[] args) {
        fun((t)->{
            return t.length()>2?true:false;
        },"小黄人");
    }
    public static void fun(Predicate<String> predicate,String name){
        boolean test = predicate.test(name);
        System.out.println("名字长度是否大于2:"+test);
    }
}

3. 方法引用

如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,没必要再写重复的逻辑,可以直接"引用"过去。

package demo07;

import java.util.function.Consumer;

public class Test07 {
    public static void main(String[] args) {
        fun(Test07::sum);
    }

    public static void fun(Consumer<int[]> consumer){
        int[] arr={1,2,3,4,5};
        consumer.accept(arr);
    }

    public static void sum(int[] arr){
        int sum=0;
        for(int n:arr){
            sum+=n;
        }
        System.out.println("数组的和为:"+sum);
    }
}

方法引用是Lambda表达式的一种简写形式,如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见形式:
        对象::实例方法
        类::静态方法
        类::实例方法
        类::new
请注意其中的双冒号 :: 写法,这被称为"方法引用",是一种新的语法。

方法引用的分类:

3.1 静态方法引用

对应的Lambda表达式:    (args)->类名.staticMethod(args)

package demo07;

import java.util.function.Consumer;

public class Test07 {
    public static void main(String[] args) {
//        fun((arr)->Test07.sum(arr));
        fun(Test07::sum);
    }

    public static void fun(Consumer<int[]> consumer){
        int[] arr={1,2,3,4,5};
        consumer.accept(arr);
    }

    public static void sum(int[] arr){
        int sum=0;
        for(int n:arr){
            sum+=n;
        }
        System.out.println("数组的和为:"+sum);
    }
}

3.2 实例方法引用

对应的Lambda表达式:    (args)->inst.instMethod(args)

package demo08;

import java.util.function.Supplier;

public class Test08 {
    public static void main(String[] args) {
        User user = new User("暧昧",18);
        //Supplier<String> supplier = ()->user.getName();
        Supplier<String> supplier = user::getName;
        System.out.println(supplier.get());
    }
}
class User{
    private String name;
    private Integer age;

    public User() {
    }

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

3.3 对象方法引用

对应的Lambda表达式:    (inst,args)->inst.instMethod(args)

package demo09;

import java.util.function.BiFunction;

public class Test09 {
    public static void main(String[] args) {
//        BiFunction<String,String,Boolean> biFunction = (x,y)->x.equals(y);
        BiFunction<String,String,Boolean> biFunction = String::equals;
        Boolean apply = biFunction.apply("hello", "world");
        System.out.println(apply);
    }
}

3.4 构造方法引用

对应的Lambda表达式:    (args)->new 类名(args)

package demo10;

import java.util.function.Function;

public class Test10 {
    public static void main(String[] args) {
//        Function<String,String> function = (x)->new String(x);
        Function<String,String> function = String::new;
        String hello = function.apply("hello");
        System.out.println(hello);
    }
}

4. Stream流

Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作.

4.1 Stream流的原理

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

4.2 如何获取Stream流对象

package demo12;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Test12 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("暧昧");
        list.add("小黄人");
        list.add("大yelou");
        Stream<String> stream = list.stream();

        Integer[] arr = {1,5,8,10,15};
        Stream<Integer> stream1 = Arrays.stream(arr);

        Stream<String> stream2 = Stream.of("张三", "李四", "王五", "刘六");

        IntStream stream3 = IntStream.of(1, 2, 3, 5, 6);

        //上面都是串行流,这个是并行流。如果流中的数据量足够大,并行流可以加快速度。
        Stream<String> stringStream = list.parallelStream();
    }
}

4.3 Stream流中常见的api

中间操作api:一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。

终止操作api:一个终止操作,执行中间操作链,并产生结果,返回类型不在是Stream流对象。

package demo13;

import java.util.*;
import java.util.stream.Collectors;

public class Test13 {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //输出country为英国的元素
        //personList.stream().filter(item -> item.getCountry().equals("英国")).forEach(System.out::println);

        //输出sex为F的元素
        //personList.stream().filter(item->item.getSex()=='F').forEach(System.out::println);

        //只要name 和 age , 原来流中每个元素转换成另一种格式。
        // map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
//        personList.stream().map(item->{
//            Map<String,Object> map = new HashMap<>();
//            map.put("name",item.getName());
//            map.put("age",item.getAge());
//            return map;
//        }).forEach(System.out::println);

        //根据年龄排序
        //personList.stream().sorted((o1,o2)->o1.getAge()-o2.getAge()).forEach(System.out::println);

        //输出年龄最大的
        //Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
        //System.out.println(max.get());

        //输出年龄最小的
        //Optional<Person> min = personList.stream().min((o1, o2) -> o1.getAge() - o2.getAge());
        //System.out.println(min);

        //规约reduce
        //求集合中所有人的年龄和
        //Optional<Integer> reduce = personList.stream().map(item -> item.getAge()).reduce((a, b) -> a + b);
        //System.out.println(reduce.get());

        //求a有初始化值的规约
        //Integer reduce = personList.stream().map(item -> item.getAge()).reduce(20, (a, b) -> a + b);
        //System.out.println(reduce);

        //collect搜集  搜集年龄大于20且性别为F的
        //List<Person> collect = personList.stream().filter(item -> item.getAge() > 20).filter(item -> item.getSex() == 'F').collect(Collectors.toList());

        //findFirst() 方法根据命名可以大致知道是获取Optional流中的第一个元素。
        //findAny() 方法是获取Optional 流中任意一个,存在随机性,其实里面也是获取元素中的第一个。(适用于并行流)
        //Optional<Person> first = personList.stream().filter(item -> item.getSex() == 'F').findFirst();
        //System.out.println(first.get());

        //allMatch  查询所有元素都符合条件则返回true
        //boolean b = personList.stream().allMatch(item -> item.getAge() > 17);
        //System.out.println(b);

        //anyMatch  查询任一元素有一个符合条件则返回true
        //boolean b = personList.stream().anyMatch(item -> item.getAge() > 23);
        //System.out.println(b);

        //noneMatch 查询没有一个元素符合我们的条件则返回true
        //boolean b = personList.stream().noneMatch(item -> item.getAge() > 23);
        //System.out.println(b);
    }
}
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public Person() {
    }

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }
}

5. 新增了日期时间类

Date日期时间类的缺点:
        1.设计比较乱,Date日期在java.util和java.sql都有,而且它的时间格式转换类在java.text包下
        2.线程不安全。

新增的日期时间类:

LocalDate: 表示日期类。yyyy-MM-dd

LocalTime: 表示时间类。 HH:mm:ss

LocalDateTime: 表示日期时间类 yyyy-MM-dd t HH:mm:ss sss

DatetimeFormatter:日期时间格式转换类。

Instant: 时间戳类。

Duration: 用于计算两个日期类

public class Test {
    public static void main(String[] args) {
        //获取当前日期
        LocalDate now = LocalDate.now(); 
        //指定日期
        LocalDate date = LocalDate.of(2022, 8, 23);

        //当前时间
        LocalTime now1 = LocalTime.now();
        LocalTime of = LocalTime.of(17, 30, 20, 600);

        //获取当前日期时间
        LocalDateTime now2 = LocalDateTime.now();
        LocalDateTime now3 = LocalDateTime.of(2022,6,20,17,45,20);
        Duration between = Duration.between(now2, now3);
        System.out.println(between.toHours());


        DateTimeFormatter dateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //把字符串转换为日期格式
        LocalDate parse = LocalDate.parse("1999-12-12", dateTimeFormatter);
        //把日期格式转换为字符串
        String format = parse.format(dateTimeFormatter);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值