【Java8新特性】让你想象不到代码前所未有的简单化编程(lambda表达式、函数式接口、方法引用、Stream API概论以及案例详解)

所有知识体系文章,GitHub已收录,欢迎Star!再次感谢,愿你早日进入大厂!

GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual

搜索关注微信公众号“码出Offer”,送你学习福利资源!

Java8新特性让你的代码更加简单化!


目录


一、Lambda表达式
二、使用Lambda的注意事项
三、函数式接口
四、方法引用
五、Stream API
六、Stream API应用


一、Lambda表达式

  • 概念: 允许把函数作为一个方法的参数(函数作为参数传递到方法中)
	<函数式接口> <变量名> = (参数1, 参数2...) -> {
		//方法体
	}

Lambda表达式使用方式

public class TestLambdas {
    public static void main(String[] args) {
        /*匿名内部类会生成.class文件*/
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程启动");
            }
        });
        thread.start();

        /*lambda表达式简写(省略了内部类run方法)*/
        Runnable task = () -> {
            System.out.println("我才是第一个子线程");
        };
        Thread thread1 = new Thread(task);
        thread1.start();

        /*lambda再次简写(省略了对象接收并启动线程)*/
        new Thread(() -> {
            System.out.println("我是第二个子线程");
        }).start();

        /*lambdas最简写版(省略了{})*/
        new Thread(() -> System.out.println("我是第三个子线程")).start();
    }
}

二、使用Lambda的注意事项

  • 新的操作符 -> (箭头操作符)
    • (参数1, 参数2) -> 表示参数列表
    • -> { } 方法体
  • 形参列表的数据类型会自动推断
  • 如果形参列表为空,只需保留()
  • 如果形参只有一个,()可以省略,只要参数名字即可
  • 如果执行语句只有1句,且无返回值,{}可以省略
  • 若有返回值,仍想省略{},return也省略。保证执行语句只有1句
  • Lamdba表达式不会生成单独的内部类文件
  • lambda访问局部变量时,变量要修饰final,如果没有加,会自动添加
import java.util.ArrayList;
import java.util.List;

public class TestEmployee {
    public static void main(String[] args) {
        List<Employee> list = new ArrayList<Employee>();
        list.add(new Employee("Sendy", 19, 2500));
        list.add(new Employee("Jack", 20, 5000));
        list.add(new Employee("Mary", 18, 35000));
        list.add(new Employee("Join", 25, 50000));
        list.add(new Employee("Ziph", 22, 120000));

        System.out.println("---------------------------------获取员工年龄大于20岁的员工信息------------------------------------");

        /**
         * 获取员工年龄大于20岁的员工信息
         *
         * 打印结果:
         * Employee{name='Jack', age=20, salary=5000.0}
         * Employee{name='Join', age=25, salary=50000.0}
         * Employee{name='Ziph', age=22, salary=120000.0}
         */
        List<Employee> ageList = getAgeEmployee(list);
        for (Employee e : ageList) {
            System.out.println(e);
        }

        /**
         * 利用lambda写法传入规则来获取员工年龄大约20岁的员工信息
         */
        List<Employee> ageList1 = getAgeAndSalary(list, e -> e.getAge() >= 20);
        for (Employee e : ageList1) {
            System.out.println(e);
        }

        System.out.println("---------------------------------获取员工工资大于10000元的员工信息------------------------------------");

        /**
         * 获取员工工资大于10000元的员工信息
         *
         * 打印结果:
         * Employee{name='Mary', age=18, salary=35000.0}
         * Employee{name='Join', age=25, salary=50000.0}
         * Employee{name='Ziph', age=22, salary=120000.0}
         */
        List<Employee> salaryList = getSalaryEmployee(list);
        for (Employee e : salaryList) {
            System.out.println(e);
        }

        /**
         * 利用lambda写法传入规则来获取员工工资大于10000元的员工信息
         */
        List<Employee> salaryList1 = getAgeAndSalary(list, e -> e.getSalary() >= 10000);
        for (Employee e : salaryList1) {
            System.out.println(e);
        }

        System.out.println("---------------------------------获取员工年龄大于20岁并且工资大于10000元的员工信息------------------------------------");

        /**
         * 利用lambda写法传入规则来获取员工年龄大于20岁并且工资大于10000元的员工信息
         *
         * 打印结果:
         * Employee{name='Join', age=25, salary=50000.0}
         * Employee{name='Ziph', age=22, salary=120000.0}
         */
        List<Employee> ageAndSalaryList = getAgeAndSalary(list, e -> e.getSalary() >= 10000 && e.getAge() >= 20);
        for (Employee e : ageAndSalaryList) {
            System.out.println(e);
        }

        /**
         * 利用Stream API过滤,传入规则来获取员工年龄大于20岁并且工资大于10000元的员工信息
         * 注意:也可以把(e)的括号省略掉
         */
        list.stream().filter((e) -> e.getSalary() >= 10000 && e.getAge() >= 20).forEach(System.out::println);
    }

    /**
     * 利用函数式接口来制定规则创建方法
     *
     * @param list
     * @param predicate 需要传入规则(lambda)
     * @return
     */
    public static List<Employee> getAgeAndSalary(List<Employee> list, MyPredicate<Employee> predicate) {
        List<Employee> newList = new ArrayList<>();
        for (Employee e : list) {
            /*调用规则!只使用规则,不用关心过程!*/
            if (predicate.test(e)) {
                newList.add(e);
            }
        }
        return newList;
    }

    /**
     * 返回员工年龄大于等于20岁的员工信息的方法
     *
     * @param list
     * @return
     */
    public static List<Employee> getAgeEmployee(List<Employee> list) {
        List<Employee> newList = new ArrayList<>();

        for (Employee e : list) {
            if (e.getAge() >= 20) {
                newList.add(e);
            }
        }
        return newList;
    }

    /**
     * 返回员工工资大于10000元的员工信息的方法
     *
     * @param list
     * @return
     */
    public static List<Employee> getSalaryEmployee(List<Employee> list) {
        List<Employee> newList = new ArrayList<>();

        for (Employee e : list) {
            if (e.getSalary() >= 10000) {
                newList.add(e);
            }
        }
        return newList;
    }
}

/**
 * 规则
 * 能力
 * @param 
 */
public interface MyPredicate<T> {
    boolean test(T t);
}

/**
 * 员工类
 */
class Employee {
    private String name;
    private int age;
    private double salary;

    public Employee() {
    }

    /**
     * @param name      姓名
     * @param age       年龄
     * @param salary    工资
     */
    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    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;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }
}

三、函数式接口(java.util.function)

  • 如果一个接口只有一个抽象方法,则该接口成为函数式接口(但是可以有多个非抽象方法的接口)
  • Java 8为函数式接口引入了一个新注解 @FunctionalInterface,主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错
  • 每一个Lambda表达式都对应一个类型,通常都是接口类型。而“函数式接口”是仅仅包含一个抽象方法的接口 每一个类型Lambda表达式 都会匹配这个方法中
  • 默认方法不算抽象方法,可以在函数式接口中添加
  • 内置四个核心函数式接口:(点击即跳转案例详解)
    • Consumer< T > 消费型接口——void accept(T t);
      • 传入一个参数,无返回值,纯消费
      • 应用场景: 因为没有出参,所以常用于打印、发送短信等消费动作
    • Supplier< T > 供给型接口——T get();
      • 无参数传入,返回一个结果
      • 应用场景: 常用于符合条件时调用获取结果;运行结果提前定义,但不运行
    • Function 函数型接口——R apply(T t);
      • 传入一个参数,返回一个结果
    • Predicate< T > 断言型接口——boolean test(T t);
      • 传入一个参数,返回一个boolean结果
      • 应用场景: 常用于条件判断


Consumer< T > 消费型接口案例详解

import java.util.function.Consumer;

/**
 * Consumer< T > 消费型接口
 * void accept(T t);
 * 传入一个参数,无返回值,纯消费
 */
public class TestConsumer {
    public static void main(String[] args) {
        /**
         * 打印结果:
         * 今天挣了1000.0元钱!
         */
        method1(1000, a -> System.out.println("今天挣了" + a + "元钱!"));

        /**
         * 打印结果:
         * 0 1 2 3 4 5 6 7 8 9 10
         */
        method2(10, a -> {
            for (int i = 0; i <= a; i++) {
                System.out.print(i + " ");
            }
        });

        //换行
        System.out.println();

        /**
         * 打印结果:
         * 0 1 2 3 4 5 6 7 8 9 10
         */
        method3(a -> {
            for (int i = 0; i <= a ; i++) {
                System.out.print(i + " ");
            }
        });
    }

    /**
     * 因为方法是被lambda写法调用的,所以也可以把public换为private
     * @param money         需要传入的金钱参数
     * @param consumer      需要传入的具体操作
     */
    public static void method1(double money, Consumer<Double> consumer) {
        consumer.accept(money);
    }

    /**
     * 同理,也是因为方法是被lambda写法调用的,所以也可以把public换为private
     * @param num       需要传入的num值
     * @param consumer  需要传入的具体操作
     */
    private static void method2(int num, Consumer<Integer> consumer) {
        consumer.accept(num);
    }

    /**
     * 因为method2需要传入的参数为num为10是变的,所以也可以在方法中定义为10(不灵活了)
     * @param consumer  需要传入的具体操作
     */
    private static void method3(Consumer<Integer> consumer) {
        consumer.accept(10);
    }
}


Supplier< T > 供给型接口案例详解

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

/**
 * Supplier< T > 供给型接口
 * T get();
 * 无参数传入,返回一个结果
 */
public class TestSupplier {
    public static void main(String[] args) {
        /**
         * 获得10个100以内的随机数相加结果
         */
        int sum = getSum(10, () -> new Random().nextInt(100));
        System.out.println(sum);
        
        /**
         * 获取0~50的和
         */
        Supplier<Integer> sum1 = () -> {
            int count = 0;
            for (int i = 0; i <= 50; i++) {
                count += i;
            }
            return count;
        };
        System.out.println(sum1.get());

        /**
         * 获取51~100的和
         */
        Supplier<Integer> sum2 = () -> {
            int count = 0;
            for (int i = 51; i <= 100; i++) {
                count += i;
            }
            return count;
        };
        System.out.println(sum2.get());
    }

	/**
     * 因为方法是被lambda写法调用的,所以也可以把public换为private
     * @param num           需要传入的num值
     * @param supplier      需要传入的具体操作
     * @return
     */
    public static int getSum(int num, Supplier<Integer> supplier) {
        int sum = 0;
        for (int i = 0; i <= num; i++) {
            sum += supplier.get();
        }
        return sum;
    }
}


Function 函数型接口案例详解

import java.util.function.Function;

/**
 * Function 函数型接口
 * R apply(T t);
 * 传入一个参数,返回一个结果
 */
public class TestFunction {
    public static void main(String[] args) {
        /**
         * 注意:可以简化为方法引用的!(此处我没有改!)
         * 将字符串全转换为大写
         * toUpperCase()
         * 打印结果:
         * HELLO
         */
        String up = stringUpper("hello", s -> s.toUpperCase());
        System.out.println(up);

        /**
         * 注意:可以简化为方法引用!(此处改为了 类::静态方法 的方法引用!)
         * 将字符串前后端空格去掉
         * trim()
         * 打印结果:
         * Ziph(无空格)
         */
        String trims = stringUpper("           Ziph              ", String::trim);
        System.out.println(trims);
    }

    /**
     * 注意:因为方法是被lambda写法调用的,所以也可以把public换为private
     * @param s
     * @param function
     * @return
     */
    public static String stringUpper(String s, Function<String, String> function) {
        return function.apply(s);
    }
}


Predicate< T > 断言型接口案例详解

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

/**
 * Predicate< T > 断言型接口
 * boolean test(T t);
 * 传入一个参数,返回一个boolean结果
 */
public class TestPredicate {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("张三");
        list.add("李四");
        list.add("王五");
        list.add("张龙");
        list.add("赵虎");

        /**
         * 筛选出字符串名字开头为张的人的名字
         */
        List<String> stringList = filter(list, s -> s.startsWith("张"));

        /*利用Stream API的forEach方法和引用方法System.out::println(对象::实例方法)*/
        stringList.forEach(System.out::println);

        /*普通foreach遍历方式*/
        for (String s : stringList) {
            System.out.println(s);
        }
    }

    /**
     * 因为方法是被lambda写法调用的,所以也可以把public换为private
     *
     * @param list
     * @param predicate
     * @return
     */
    public static List<String> filter(List<String> list, Predicate<String> predicate) {
        List<String> newList = new ArrayList<String>();
        for (String s : list) {
            /*省略了具体判断方法(改为使用lambda简化)*/
            if (predicate.test(s)) {
                newList.add(s);
            }
        }
        return newList;
    }
}

@FunctionalInterface注解

public class TestFunctionInterface {
    public static void main(String[] args) {
        test(() -> System.out.println("This is a Method"));
    }

    public static void test(MyPredicates myPredicate) {
        myPredicate.method();
    }
}

/**
 * 注意:一个接口只有一个抽象方法,则该接口成为函数式接口。不能有多个抽象方法,但是可以有多个非抽象方法
 * 引入@FunctionalInterface注解,他就会帮你检查你写的接口是否符合函数式接口,不合符会出现编译错误!
 */
@FunctionalInterface
interface MyPredicates {
    void method();
}

四、方法引用

  • 方法引用是Lambda表达式的一种简写形式,如果Lamdba表达式方法体中只是调用一个特定的已存在的方法,则可以使用方法引用
  • 通俗来说: Lambda表达式简化了匿名内部类,方法引用简化了Lambda表达式
  • 使用 :: 操作符将对象或类和方法名的名字分隔开来
    • 对象 :: 实例方法
    • 类 :: 静态方法
    • 类 :: 实例方法
    • 类 :: new
  • 注意:调用的方法参数列表与返回值类型,要与函数型接口中的方法参数列表与返回值类型一致

方法引用的使用案例详解

import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Lambda表达式简化了匿名内部类,方法引用简化了Lambda表达式
 * 1.对象::方法名
 * 2.类名::静态方法
 * 3.类名::实例方法
 * 4.类名::new
 */
public class TestMethodReferences {
    public static void main(String[] args) {
        Employees employees = new Employees("Ziph", 18);

        /**
         * 1.对象::方法名
         * 
         * 两种方法的打印结果:
         * Ziph
         * Ziph
         */
        /*lambda表达式*/
        Consumer<String> consumer = s -> System.out.println(s);
        consumer.accept("Ziph");
        /*对象::方法名的方法引用*/
        Consumer<String> consumer1 = System.out::println;
        consumer1.accept("Ziph");


        /*lambda表达式*/
        Supplier<String> supplier = () -> employees.getName();
        supplier.get();
        /*对象::方法名的方法引用*/
        Supplier<String> supplier1 = employees::getName;
        supplier1.get();

        /**
         * 2.类名::静态方法(不常用)
         * 
         * 两种方法的打印结果:
         * -1
         * -1
         */
        /*lambda表达式*/
        Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
        System.out.println(comparator.compare(1, 2));
        /*类名::静态方法的方法引用*/
        Comparator<Integer> comparator1 = Integer::compare;
        System.out.println(comparator1.compare(1, 2));

        /**
         * 3.类名::实例方法
         * 
         * 两种方法的打印结果:
         * Ziph
         * Ziph
         */
        /*lambda表达式*/
        Function<Employees, String> function = e -> e.getName();
        System.out.println(function.apply(employees));
        /*类名::实例方法的方法引用*/
        Function<Employees, String> function1 = Employees::getName;
        System.out.println(function1.apply(employees));

        /**
         * 4.类名::new(类名::构造方法)
         * 
         * 两种方法的打印结果:
         * Employees{name='null', age=null}
         * Employees{name='null', age=null}
         */
        /*lambda表达式*/
        Supplier<Employees> s = () -> new Employees();
        System.out.println(s.get());
        /*类名::new的方法引用*/
        Supplier<Employees> s1 = Employees::new;
        System.out.println(s1.get());
    }
}

class Employees {
    private String name;
    private Integer age;

    public Employees() {
    }

    public Employees(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 "Employees{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

五、Stream API

  • Stream是Java8中处理数组、集合的抽象概念
  • 可以执行非常复杂的查找、过滤、映射等操作
  • 注意:Stream里存储的是数据的操作,自身不保存数据,也不修改集合或数组的数据结构(给定操作规则,Stream去执行结果)
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class TestCreateStream {
    public static void main(String[] args) {
        /*Stream API要求:集合、数组*/
        List<String> list = new ArrayList<>();
        list.add("Join");
        list.add("Marry");
        list.add("Jack");
        list.add("angelababy");

        /**
         * 指定Stream API做什么,而不是怎么做
         * Stream里存储的是数据的操作,自身不保存数据,也不修改集合或数组的数据结构
         * 分布式写Stream的过程:
         */
        /*1.创建Stream*/
        Stream<String> stream = list.stream();
        /*2.中间操作:寻找集合中名字长度大于等于5的名字*/
        Stream<String> stringStream = stream.filter(s -> s.length() >= 5);
        /*3.终止操作(最终操作)*/
        System.out.println("名字长度大于等于5的是:");
        stringStream.forEach(System.out::println);

        /**
         * 使用Stream来简化编程:
         *
         * 打印结果:
         * 名字长度大于等于5的是:
         * Marry(分布式结果)
         * angelababy
         * Marry(简化结果)
         * angelababy
         */
        list.stream().filter(s -> s.length() >= 5).forEach(System.out::println);
    }
}

六、Stream API应用(中间操作、终止操作)

  • stream串行流,适合存在线程安全问题、阻塞任务、重量级任务,以及需要使用同一事务的逻辑。
  • parallelStream并行流,适合没有线程安全问题、较单纯的数据处理任务。
    • 并行流使用多线程,则一切线程安全问题都应该是需要考虑的问题,如:资源竞争、死锁、事务、可见性等等

常用方法(中间操作)

  • Stream< T > filter(Predicate predicate); 过滤
  • Stream< T > limit(long maxSize); 截断,不超过给定数量
  • Stream< T > distinct(); 筛选,利用hashCode和equals
  • < R > Stream< R > map(Function mapper); Map指的是,传入一个T类型参数,返回一个R类型结果
  • Stream< T > sorted(); 自然排序
  • Stream< T > sorted(Comparator comparator); 定制排序
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 常用方法(中间操作)
 */
public class TestStreamMethod {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Join");
        list.add("Ziph");
        list.add("Marry");
        list.add("Zitey");
        list.add("Angelababy");

        System.out.println("---------------------------finter---------------------------");

        /**
         * Stream< T > filter(Predicate predicate);
         * 过滤
         *
         * 找出集合名字中以Z字母开头、包含h字母的名字并打印
         * 打印结果:
         * Ziph
         */
        list.stream().filter(s -> s.startsWith("Z")).filter(s -> s.contains("h")).forEach(System.out::println);

        System.out.println("---------------------------limit---------------------------");

        /**
         * Stream< T > limit(long maxSize);
         * 截断,不超过给定数量
         *
         * 从集合的第三个元素开始截断,并打印名字
         * 打印结果:
         * Join Ziph Marry
         */
        list.stream().limit(3).forEach(System.out::println);

        System.out.println("---------------------------distinct---------------------------");

        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(new Employee("李四", 18, 100));
        employeeList.add(new Employee("张三", 28, 90));
        employeeList.add(new Employee("张龙", 38, 66));
        employeeList.add(new Employee("赵虎", 16, 50));
        employeeList.add(new Employee("赵虎", 16, 50));

        /**
         * Stream< T > distinct();
         * 筛选,利用hashCode和equals
         *
         * 与重写hashCode和equals相同
         * 先判断地址、在判断hashCode、最后判断equals
         * 打印结果:
         * Employee{name='李四', age=18, score=100.0}
         * Employee{name='张三', age=28, score=90.0}
         * Employee{name='张龙', age=38, score=66.0}
         * Employee{name='赵虎', age=16, score=50.0}
         * 注意:不会改变数据结构(其集合数据结构中没有移除重复元素)
         */
        employeeList.stream().distinct().forEach(System.out::println);
        /**
         * 遍历集合中所有元素结果:
         * Employee{name='李四', age=18, score=100.0}
         * Employee{name='张三', age=28, score=90.0}
         * Employee{name='张龙', age=38, score=66.0}
         * Employee{name='赵虎', age=16, score=50.0}
         * Employee{name='赵虎', age=16, score=50.0}
         */
        employeeList.stream().forEach(System.out::println);

        System.out.println("---------------------------map---------------------------");

        /**
         * < R > Stream< R > map(Function mapper);
         * Map指的是
         * 传入一个T类型参数,返回一个R类型结果
         *
         * 打印集合中所有名字
         * 答应结果:
         * 李四
         * 张三
         * 张龙
         * 赵虎
         * 赵虎
         */
        employeeList.stream().map(employee -> employee.getName()).forEach(System.out::println);
        /*更简化*/
        employeeList.stream().map(Employee::getName).forEach(System.out::println);

        /**
         * 字符串小写转化为大写
         * 打印结果:
         * AAA
         * BBB
         * CCC
         * DDD
         * EEE
         */
        List<String> stringList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        stringList.stream().map(String::toUpperCase).forEach(System.out::println);

        System.out.println("---------------------------sorted---------------------------");

        /**
         * Stream< T > sorted();
         * 自然排序
         *
         * sorted排序,流中的元素必须实现Comparable接口,覆盖CompareTo方法指定排序规则
         * 字符串没有指定排序规则默认遵循字典排序
         *
         * 打印结果:
         * Angelababy
         * Join
         * Marry
         * Ziph
         * Zitey
         */
        list.stream().sorted().forEach(System.out::println);
        employeeList.stream().sorted().forEach(System.out::println);

        System.out.println("---------------------------sorted(Comparator)---------------------------");

        /**
         * Stream< T > sorted(Comparator comparator);
         * 定制排序
         *
         * 根据分数排序打印结果:
         * Employee{name='赵虎', age=16, score=50.0}
         * Employee{name='赵虎', age=16, score=50.0}
         * Employee{name='张龙', age=38, score=66.0}
         * Employee{name='张三', age=28, score=90.0}
         * Employee{name='李四', age=18, score=100.0}
         */
        employeeList.stream().sorted((x, y) -> Double.compare(x.getScore(), y.getScore())).forEach(System.out::println);
    }
}

/**
 * 员工类
 */
public class Employee implements Comparable {
    private String name;
    private int age;
    private double score;

    public Employee() {
    }

    public Employee(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    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;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public int hashCode() {
        return (int) (this.name.hashCode() + this.age + this.score);
    }

    @Override
    public boolean equals(Object obj) {
        /*1.比较来给两个地址是否相等*/
        if (this == obj) {
            return true;
        }
        /*2.判断obj是否为空*/
        if (obj == null) {
            return false;
        }
        /*3.确认类型,确认是同一类型*/
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        /*4.强转类型*/
        Employee employee = (Employee) obj;
        /*5.比较*/
        if (this.name.equals(employee.getName()) && this.age == employee.getAge() && this.score == employee.getScore()) {
            return true;
        }
        return false;
    }

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

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

常用方法(终止操作)

  • long count(); //返回流中元素的总个数
  • void forEach(Consumer action); //遍历
  • boolean anyMatch(Predicate predicate); //是否至少匹配一个
  • boolean allMatch(Predicate predicate); //是否匹配所有元素
  • boolean noneMatch(Predicate predicate); //是否没有匹配
  • Optional< T > finalFirst(); //返回第一个
  • Optional< T > findAny(); //返回任意
  • Optional< T > min(Comparator comparator); //返回最小
  • Optional< T > max(Comparator comparator); //返回最大
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 常用方法(终止操作)
 */
public class TestEndMethod {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("Join");
        list.add("Ziph");
        list.add("Marry");
        list.add("Zitey");
        list.add("Angelababy");

        System.out.println("---------------------------forEach---------------------------");

        /**
         * void forEach(Consumer action);
         * 遍历
         * 在前面的案例已经用过多次了!
         * 执行结果:
         * Join
         * Ziph
         * Marry
         * Zitey
         * Angelababy
         */
        list.stream().forEach(System.out::println);
        /*stream可以简化省略*/
        list.forEach(System.out::println);

        System.out.println("---------------------------count---------------------------");

        /**
         * long count();
         * 返回流中元素的总个数
         * 注意:自身是long类型的,因为int类型是8位,所以有可能会超出!
         * 我这里是用强转的int类型!
         * 打印结果:
         * 名字长度大于等于5的名字个数为:3
         */
        int count = (int) list.stream().filter(s -> s.length() >= 5).count();
        System.out.println("名字长度大于等于5的名字个数为:" + count);

        System.out.println("---------------------------anymatch---------------------------");

        /**
         * boolean anyMatch(Predicate predicate);
         * 是否至少匹配一个
         * @解释:筛选出名字长度大于等于5的全部名字中,是否匹配包含一个名字开头字母是Z,是则返回true,否则返回false
         * 打印结果:
         * true
         */
        boolean b1 = list.stream().filter(s -> s.length() >= 5).anyMatch(s -> s.startsWith("Z"));
        System.out.println(b1);

        System.out.println("---------------------------allmatch---------------------------");

        /**
         * boolean allMatch(Predicate predicate);
         * 是否匹配所有元素
         * @解释:筛选出名字长度大于等于5的全名名字中,是否匹配所有名字开头字母是A,是则返回true,否则返回false
         * 打印结果:
         * false
         */
        boolean b2 = list.stream().filter(s -> s.length() >= 5).allMatch(s -> s.startsWith("A"));
        System.out.println(b2);

        System.out.println("---------------------------nonematch---------------------------");

        /**
         * boolean noneMatch(Predicate predicate);
         * 是否没有匹配
         * @解释:筛选出名字长度大于等于5的全名名字中,是否匹配没有名字开头字母是Y,是则返回true,否则返回false
         * 打印结果:
         * true
         */
        boolean b3 = list.stream().filter(s -> s.length() >= 5).noneMatch(s -> s.startsWith("Y"));
        System.out.println(b3);

        System.out.println("---------------------------findfirst---------------------------");

        /**
         * Optional< T > finalFirst();
         * 返回第一个
         * @解释:筛选出名字长度大于等于5的全名名字中,找出第一个名字
         * @注意:得出的结果是Optional类型
         * 打印结果:
         * Marry
         */
        String str = list.stream().filter(s -> s.length() >= 5).findFirst().get();
        System.out.println(str);

        System.out.println("---------------------------findany---------------------------");

        /**
         * Optional< T > findAny();
         * 返回任意
         * @解释:返回任意一个集合中的名字
         */
        Optional<String> option = list.parallelStream().findAny();
        System.out.println(option.get());

        System.out.println("---------------------------max---------------------------");

        List<Employee> employeeList = new ArrayList<>();
        employeeList.add(new Employee("李四", 18, 100));
        employeeList.add(new Employee("张三", 28, 90));
        employeeList.add(new Employee("张龙", 38, 66));
        employeeList.add(new Employee("赵虎", 16, 50));
        employeeList.add(new Employee("赵虎", 16, 50));

        /**
         * Optional< T > max(Comparator comparator);
         * 返回最大
         * @解释:在集合中返回年龄最大人的信息
         * 打印结果:
         * Employee{name='张龙', age=38, score=66.0}
         */
        Optional<Employee> max = employeeList.stream().max((x, y) -> x.getAge() - y.getAge());
        System.out.println(max.get());

        System.out.println("---------------------------min---------------------------");

        /**
         * Optional< T > min(Comparator comparator);
         * 返回最小
         * @解释:在集合中返回年龄最小的人信息
         * 打印结果:
         * Employee{name='赵虎', age=16, score=50.0}
         */
        Optional<Employee> min = employeeList.stream().min((x, y) -> x.getAge() - y.getAge());
        System.out.println(min.get());
    }
}

public class Employee implements Comparable {
    private String name;
    private int age;
    private double score;

    public Employee() {
    }

    public Employee(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    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;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public int hashCode() {
        return (int) (this.name.hashCode() + this.age + this.score);
    }

    @Override
    public boolean equals(Object obj) {
        /*1.比较来给两个地址是否相等*/
        if (this == obj) {
            return true;
        }
        /*2.判断obj是否为空*/
        if (obj == null) {
            return false;
        }
        /*3.确认类型,确认是同一类型*/
        if (this.getClass() != obj.getClass()) {
            return false;
        }
        /*4.强转类型*/
        Employee employee = (Employee) obj;
        /*5.比较*/
        if (this.name.equals(employee.getName()) && this.age == employee.getAge() && this.score == employee.getScore()) {
            return true;
        }
        return false;
    }

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

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

【Java8新特性】让你想象不到代码前所未有的简单化编程(lambda表达式、函数式接口、方法引用、Stream API概论以及案例详解)_第1张图片

你可能感兴趣的:(《JavaSE基础》)