快速掌握java8新特性

Lambda表达式

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

基本语法

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

   //方法体

};

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

如果一个接口只有一个抽象方法,则该接口称为函数式接口

可以使用@FunctionalInterface注解来检测是否为函数式接口

快速掌握java8新特性

常见的函数式接口

快速掌握java8新特性

用Consumer举个例子:

快速掌握java8新特性

方法引用

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

常见的形式:

对象::实例方法

类::静态方法

类::实例方法

类::new

public class Demo2 {
    public static void main(String[] args) {
        //对象::实例方法
        Consumer<String> consumer = System.out::println;
        consumer.accept("北京");

        //类::静态方法
        Comparator<Integer> comparator = Integer::compare;
        System.out.println(comparator.compare(1,2));

        //类::实例方法
       Function<User,String> f = User::getUserName;
        System.out.println(f);
        //类::new
        Supplier<User> user = User::new;
        System.out.println(user.get());
    }
}

Stream流

什么是Stream

流中保存对集合或者数组的操作,和集合类似,但是集合中保存的是数据,Stream中保存的是操作。就像工厂里的机械流水线。

Stream的特点:

  • Stream自己不会存储元素
  • Stream不会改变源对象,相反,它会返回一个持有结果的新Stream
  • Stream的操作是延迟执行的,这就意味着它会等到需要结果的时候才执行

创建Stream

  • 通过Collection对象的Stream()或parallelStream
  • 通过Arrays类的stream()方法
  • 通过Stream接口的of()、iterate()、generate()方法
  • 通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
public class Demo3 {
    public static void main(String[] args) {
        //通过Collection对象的Stream()或parallelStream
        ArrayList<String> list = new ArrayList<>();
        list.add("北京");
        list.add("武汉");
        list.add("南京");
        Stream<String> stream = list.stream();
        stream.forEach(System.out::println);
        //通过Arrays类的stream()方法
        String[] arr = {"a","b","c"};
        Stream<String> stream1 = Arrays.stream(arr);
        stream1.forEach(System.out::println);
        //通过Stream接口的of()、iterate()、generate()方法
        Stream<Integer> integerStream = Stream.of(10, 20, 30);
        integerStream.forEach(System.out::println);
        System.out.println("=========迭代流");
        Stream<Integer> iterate = Stream.iterate(0, x -> x + 2);
        iterate.limit(3).forEach(System.out::println);
        System.out.println("========生成流");
        Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(10));
        generate.limit(4).distinct().forEach(System.out::println);
        //通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
        IntStream intStream = IntStream.of(15, 20, 25);
        //range  rangeClosed区别 (10,50) (10,50]
        IntStream range = IntStream.range(10, 50);
        IntStream rangeClosed = IntStream.rangeClosed(10, 50);
        System.out.println(intStream.max());
        range.forEach(System.out::println);
        System.out.println("--------rangeClosed");
        rangeClosed.forEach(System.out::println);
    }
}

中间操作

User类

public class User {
    private String userName;
    private Integer age;

    public User() {
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User)) return false;

        User user = (User) o;

        if (!Objects.equals(userName, user.userName)) return false;
        return Objects.equals(age, user.age);
    }

    @Override
    public int hashCode() {
        int result = userName != null ? userName.hashCode() : 0;
        result = 31 * result + (age != null ? age.hashCode() : 0);
        return result;
    }
}

Stream流中间操作

import java.util.ArrayList;
import java.util.Comparator;

public class Demo4 {
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("张三",21));
        list.add(new User("李四",22));
        list.add(new User("王五",23));
        list.add(new User("马六",20));
        list.add(new User("马六",20));
        //中间操作  1、filter过滤  2、limit 3、skip 4、distinct 去重  5、sorted排序
        System.out.println("-------filter过滤");
        list.stream()
                .filter(e -> e.getAge() > 22)
                .forEach(System.out::println);
        System.out.println("-------limit限制");
        list.stream()
                .limit(2)
                .forEach(System.out::println);
        System.out.println("-------skip跳过");
        list.stream()
                .skip(2)
                .forEach(System.out::println);
        System.out.println("-------distinct去重");
        list.stream()
                .distinct()
                .forEach(System.out::println);
        System.out.println("-------sorted排序");
        list.stream()
                .sorted(Comparator.comparingInt(User::getAge))
                .forEach(System.out::println);
        System.out.println("---中间操作2  map");
        list.stream()
                .map(User::getUserName)
                .forEach(System.out::println);
    }
}

终止操作

forEach、min、max、count

reduce、collect

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<User> list = new ArrayList<>();
        list.add(new User("张三",21));
        list.add(new User("李四",22));
        list.add(new User("王五",23));
        list.add(new User("马六",20));
        System.out.println("------min");
        Optional<User> min = list.stream()
                .min(Comparator.comparingInt(User::getAge));
        System.out.println(min.get() );
        System.out.println("------max");
        Optional<User> max = list.stream()
                .max(Comparator.comparingInt(User::getAge));
        System.out.println(max.get());
        System.out.println("------count");
        long count = list.stream().count();
        System.out.println("人数:"+count);
        System.out.println("----reduce");
        Optional<Integer> reduce = list.stream()
                .map(User::getAge)
                .reduce(Integer::sum);
        System.out.println("年龄之和:"+reduce);
        System.out.println("-------collect");
        List<String> collect = list.stream()
                .map(User::getUserName)
                .collect(Collectors.toList());
        collect.forEach(System.out::println);
    }
}

日期格式化问题

我们知道SimpleDateFormat是线程不安全的

快速掌握java8新特性

那么在java8中我们可以使用DateTimeFormatter

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

public class Demo6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
        ExecutorService pool = Executors.newFixedThreadPool(10);
        Callable<LocalDate> callable = new Callable<LocalDate>() {
            @Override
            public LocalDate call() throws Exception {
                return LocalDate.parse("20210602",dtf);
            }
        };

        List<Future<LocalDate>> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Future<LocalDate> future = pool.submit(callable);
            list.add(future);
        }
        for (Future<LocalDate> future:list) {
            System.out.println(future.get());
        }
        pool.shutdown();
    }
}

上一篇:【Java】Java8 LocalDate日期时间用法总结


下一篇:Java8新特性的使用