Java8新特性-Lambda表达式-Stream API等(学习笔记)

Java8新特性-Lambda表达式-Stream API等_尚硅谷__李贺飞
内容:

  1. lambda表达式(重点)
  2. 函数式表达式
  3. 方法引用与构造器引用
  4. Stream API(重点)
  5. 接口中的默认方法与静态方法
  6. 新实践日期API
  7. 其他新特性

lambda表达式(重点)

为什么使用lambda表达式

是一段匿名函数,写出更加简洁的代码

// 创建集合对象
List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90),
            new Employee("王武",35,4567.90),
            new Employee("王二",45,9090.90),
            new Employee("李四",34,567.90),
            new Employee("小平",18,9090.90)
    );

需求:获取当前公司中员工年龄大于35的员工信息

@Test
    public void test4(){
        List<Employee> list = filterEmployees(employees);
        for (Employee employee : list) {
            System.out.println(employee);
        }
    }
    // 过滤,找到满足条件的集合
    public List<Employee> filterEmployees(List<Employee> employees){
        List<Employee> emps = new ArrayList<>();
        for (Employee emp : employees) {
            if (emp.getAge() >= 35){
                emps.add(emp);
            }
        }
        return emps;
    }

需求1:获取当前公司中员工年龄大于35的员工信息
需求2: 获取当前公司中员工工资大于5000的员工信息

优化一:采用策略设计模式
创建一个接口MyPredicate
创建接口 MyPredicate 的实现类,用作筛选员工

   @Test
    public void test5(){
        List<Employee> list = filterEmployee(this.employees, new FilterEmployeeByAge());
        for (Employee employee : list) {
            System.out.println(employee);
        }
        System.out.println("-----------------------");
        
        List<Employee> list1 = filterEmployee(this.employees, new FilterEmployeeBySalary());
        for (Employee employee : list1) {
            System.out.println(employee);
        }
    }
    /**
     * @param list 需要过滤的参数
     * @param mp 过滤的方法
     * @return
     */
    public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){
        List<Employee> emps = new ArrayList<>();
        for (Employee employee : list) {
            if (mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }
package com.java8.service;

public interface MyPredicate<T> {

     boolean test(T t);
}
package com.java8.service.impl;

import com.java8.pojo.Employee;
import com.java8.service.MyPredicate;
// 根据员工的年龄,过滤Employee
public class FilterEmployeeByAge implements MyPredicate<Employee> {
    @Override
    public boolean test(Employee employee) {
        return employee.getAge() >= 35;
    }
}
package com.java8.service.impl;

import com.java8.pojo.Employee;
import com.java8.service.MyPredicate;
// 根据员工的薪资,过滤Employee
public class FilterEmployeeBySalary implements MyPredicate<Employee> {
    @Override
    public boolean test(Employee employee) {
        return employee.getSalary() > 5000;
    }
}

优化方式二:匿名内部类
创建一个接口MyPredicate

// 优化方式二:匿名内部类
    @Test
    public void test6(){
        List<Employee> list = filterEmployee(this.employees, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getSalary() <= 5000;
            }
        });
        for (Employee employee : list) {
            System.out.println(employee);
        }
    }
    /**
     * @param list 需要过滤的参数
     * @param mp 过滤的方法
     * @return
     */
    public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){
        List<Employee> emps = new ArrayList<>();
        for (Employee employee : list) {
            if (mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }

优化方式三:lambada表达式

// 优化方式三:lambada表达式
    @Test
    public void test7() {
        List<Employee> list = filterEmployee(this.employees, (e) -> e.getSalary() <= 5000);
        list.forEach(System.out::println);
    }
    /**
     * @param list 需要过滤的参数
     * @param mp 过滤的方法
     * @return
     */
    public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){
        List<Employee> emps = new ArrayList<>();
        for (Employee employee : list) {
            if (mp.test(employee)){
                emps.add(employee);
            }
        }
        return emps;
    }

优化方式四:lambada表达式

// 优化方式四:lambada表达式
    @Test
    public void test8() {
        employees.stream()
                .filter((e)->e.getSalary() >= 5000)
                .limit(2)
                .forEach(System.out::println);

        System.out.println("---------");
        employees.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
    }
lambada表达式的基础语法
package com.java8.demo;

import com.java8.service.Myfun;
import org.junit.Test;
import java.util.Comparator;
import java.util.function.Consumer;

/**
 * 一、Lambda表达式的基本语法:-> 箭头操作符将lambda表达式分成两部分
 *
 *  左侧:lambda 表达式的参数列表
 *  右侧:lambda 表达式中所需要执行的功能,即 lambda体
 *
 *  语法格式一:无参数,无返回值
 *      () -> System.out.println("Hello, lambda")
 *  语法格式二:有一个参数,无返回值
 *      (c) -> System.out.println(c)
 *  语法格式三:若只有一个参数,小括号可以省略不写
 *      (c) -> System.out.println(c)
 *  语法格式四:有两个以上的参数,有返回值,并且lambda体中有多条语句
 *      Comparator com = (x,y) -> {
 *             System.out.println("函数式接口"+x+y);
 *             return Integer.compare(x, y);
 *         };
 *  语法格式五:若lambda体中只有一条语句,return 和 大括号 都可以省略不写
 *       Comparator com1 =(x,y) -> Integer.compare(x,y);
 *  语法格式六:lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,
 *
 *  二、Lambda表达式 需要函数是接口的支持
 *          函数式接口:接口中只有一个抽象方法的接口,称为函数式接口,可以使用@FunctionInterface 修饰
 *              可以检查是否是函数式接口
 *
 */
public class TestLambda2 {
    @Test
    public void test1(){
        // 注意事项: 在局部内部类中应用同级别的局部变量时,该变量定义为final
        // 1.8之前需要自己手动写final,1.8之后默认
        final int num = 0;
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello, lambda" + num);
            }
        };
        r.run();
        System.out.println("------------");
        Runnable r1 = () -> System.out.println("Hello, lambda");
        r1.run();
    }

    @Test
    public void test2(){
        Consumer<String> con = (c) -> System.out.println(c+"mii");
        con.accept("你好");
    }
    @Test
    public void test3(){
        Comparator<Integer> com = (x,y) -> {
            System.out.println("函数式接口"+x+y);
//            return x > y ? x : y;
            return Integer.compare(x, y);
        };

        Comparator<Integer> com1 =(x,y) -> Integer.compare(x,y);
        System.out.println(com.compare(1, 0));

    }

    // 需求:对一个数进行计算
    @Test
    public void test4(){
        Integer operation = operation(100, (x) -> x * x);
        System.out.println(operation);
        
    }

    public Integer operation(Integer num, Myfun mf){
        return mf.getValue(num);
    }
}

package com.java8.service;

@FunctionalInterface
public interface Myfun {

    Integer getValue(int i);
}
lambda表达式的练习

Java8新特性-Lambda表达式-Stream API等(学习笔记)_第1张图片

package com.java8.demo;

import com.java8.pojo.Employee;
import com.java8.service.MyLong;
import com.java8.service.MyString;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class TestLambda3 {
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90),
            new Employee("王武",35,4567.90),
            new Employee("王二",45,9090.90),
            new Employee("李四",34,567.90),
            new Employee("小平",18,9090.90)
    );
    @Test
    public void test1(){
        Collections.sort(employees, (e1,e2)->{
            if (e1.getAge() == e2.getAge()){
                return e1.getName().compareTo(e2.getName());
            }else {
                return Integer.compare(e1.getAge(),e2.getAge());
            }
        });
        for (Employee employee : employees) {
            System.out.println(employee);
        }
    }
    @Test
    public void test2(){
        String a = operation("adfd", (s) -> s.toUpperCase());
        System.out.println(a);

        String a1 = operation("adfduibvc", (s) -> s.substring(2,5));
        System.out.println(a1);

    }

    public String operation(String str, MyString ms){
        return ms.getValue(str);
    }

    @Test
    public void test3(){
        operation2(100L,200L,(x,y)->x+y);
    }

    public void operation2(Long l1, Long l2,MyLong<Long,Long> ml){
        System.out.println(ml.getValue(l1, l2));
    }

}

四大内置核心函数式接口

package com.java8.demo;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * java8 内置的四大核心函数式接口
 * Consumer:消费性接口
 *          void accept(T,t);
 * Supplier:  供给型接口
 *          T get();
 * Function:函数型接口
 *          R apply(T,t);
 * Predicate:断言型接口
 *          boolean test(T t);
 */
public class Testlambda4 {

    // Predicate:断言型接口
    // 将满足条件的字符串放入集合中去
    @Test
    public void test4(){
        List<String> list = Arrays.asList("huhu","lplp","lplko","kokookok","kokokoll");
        List<String> strings = filterStr(list, (str) -> str.length() > 4);
        for (String string : strings) {
            System.out.println(string);
        }
    }
    public List<String> filterStr(List<String> list, Predicate<String> pre){
        List<String> strList = new ArrayList<>();
        for (String s : list) {
            if (pre.test(s)){
                strList.add(s);
            }
        }
        return strList;
    }

    // Function:函数型接口
    // 需求:用于处理字符串
    @Test
    public void test3(){
        String newStr = strHandler("strdcsnvns  ", (str) -> str.trim());
        System.out.println(newStr);
    }
    public String strHandler(String str, Function<String,String> fun){
        return fun.apply(str);
    }

    // Supplier:  供给型接口
    // 需求:产生指定个数的整数,并放到集合当中去
    @Test
    public void test2(){
        List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 10));
        for (Integer integer : numList) {
            System.out.println(integer);
        }
    }
    public List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < num ; i++) {
            list.add(sup.get());
        }

        return list;

    }
    // Consumer:消费性接口
    @Test
    public void test1(){
        happy(100d,(x) -> System.out.println(x));
    }
    public void happy(Double d, Consumer<Double> con){
        con.accept(d);
    }
}

方法引用与构造器引用(没有听懂)

Stream流

流都是对数据的操作
首先把数据源转化成流,中间的操作处理,变成一个全新的和之前无关的流。

流到底是什么?

是数据的渠道,用于操作数据源(集合,数组等)所生成的元素序列,“集合讲的是数据,流讲的是计算”

Stream 自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才知性。
Java8新特性-Lambda表达式-Stream API等(学习笔记)_第2张图片

创建Stream流

package com.java8.demo;

import com.java8.pojo.Employee;
import org.junit.Test;

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

/**
 * 一、Stream 的基本操作
 *  1。创建Stream
 *
 *  2。中间操作
 *
 *  3。终止操作(终端操作)
 */
public class TestStreamAPI1 {
    // 创建Stream
    @Test
    public void test1(){
        // 1.可以通过Collection 系列集合提供的stream() 或者 parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();

        // 2. 通过Arrays 中的静态方法stream() 获取数组流
        Employee[] emps = new Employee[10];
        Stream<Employee> stream2 = Arrays.stream(emps);

        // 3. 通过Stream 类中的静态方法of()
        Stream<String> stream3 = Stream.of("aaa", "bbb", "ccc");

        // 4. 创建无限流
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        stream4.limit(4).forEach(System.out::println);

        // 5.生成
        Stream.generate(()->Math.random())
                .limit(5)
                .forEach(System.out::println);
    }
}

stream的中间操作_筛选与切片

多个中间可以连接起来形成一个流水线,除非流水线上的触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性操作”。

package com.java8.demo.stream;

import com.java8.pojo.Employee;
import org.junit.Test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

/**
 * 一、Stream 的基本操作
 *  1。创建Stream
 *
 *  2。中间操作
 *
 *  3。终止操作(终端操作)
 */
public class TestStreamAPI2 {
    /**
     *  中间操作:
     *
     *  筛选与切片
     * 1、filter——过滤Lambda , 从流中排除某些元素。
     * 2、limit——截断,使其元素不超过给定数量。
     * 3、skip(n) —— 跳越,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
     * 4、distinct——除重,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
     * 需要注意的一点:
     * 只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
     */
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90),
            new Employee("张三",34,9090.90),
            new Employee("张三",18,9090.90),
            new Employee("王武",35,4567.90),
            new Employee("王二",45,9090.90),
            new Employee("李四",34,567.90),
            new Employee("小平",18,9090.90)
    );
    // 内部迭代:迭代操作由Stream API完成
    @Test
    public void test1(){

        // 中间操作:不会执行任何操作
        Stream<Employee> stream = employees.stream()
                .filter((e) -> {
                    System.out.println("Stream API 中间操作");
                    return e.getAge() > 30;
                });
        // 终止操作:一次性执行全部内容,即"惰性求值"
        stream.forEach(System.out::println);
    }
    // 外部迭代
    @Test
    public void test2(){
        Iterator<Employee> iterator = employees.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }


    }
    @Test
    public void test3(){
        employees.stream()
                .filter((employee) ->{
                    System.out.println("duanlu");
                    return employee.getAge()>30;

                })
                .limit(2)
                .forEach(System.out::println);

    }
    @Test
    public void test4(){
        employees.stream()
                .filter((employee)->{
                    System.out.println("nihao");
                    return employee.getAge()>=30;
                })
                .skip(1)
                .forEach(System.out::println);
    }
    @Test
    public void test5(){
        employees.stream()
                .distinct()
                .forEach(System.out::println);
    }
}

stream映射
package com.java8.demo.stream;

import com.java8.pojo.Employee;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class TestStreamAPI3 {
    /**

	*  映射
		map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
		flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

     注释:相当于list集合的 add 和 addAll 的区别
	 */
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90),
            new Employee("王武",35,4567.90),
            new Employee("王二",45,9090.90),
            new Employee("李四",34,567.90),
            new Employee("小平",18,9090.90)
    );
    @Test
    public void test1(){
        List<String> list = Arrays.asList("aaa","bbb","ccc");
        list.stream()
                .map((s)->s.toUpperCase())
                .forEach(System.out::println);
        System.out.println("------------");

        employees.stream()
                .map(Employee::getName) // 流中的每一个元素都用到这个函数上
                .forEach(System.out::println);
        System.out.println("------------");

        // map本身得到的就是一个Stream,而执行方法后得到的还是流,在流中得到Character
        Stream<Stream<Character>> streamStream = list.stream()
                .map(TestStreamAPI3::filterCharacter); // 提取的参数"aaa",调用这个方法 {{a,a,a},{b,b,b}}

        // 遍历 -- 第一次遍历得到的还是流,

        streamStream.forEach((sm) -> {
                    sm.forEach(System.out::println);
                }
        );
        System.out.println("------------");

        list.stream()
                .flatMap(TestStreamAPI3::filterCharacter) // {a,a,a,b,b,b}
                .forEach(System.out::println);

    }

    // 该方法,用于接收字符安传,并返回一个流
    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }
}

stream排序
package com.java8.demo.stream;

import com.java8.pojo.Employee;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;

public class TestStreamAPI4 {
    /**
     * 排序
     * sorted() -- 自然排序
     * sorted(Comparator com) -- 定制排序
     */
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90),
            new Employee("张三",34,9090.90),
            new Employee("张三",18,9090.90),
            new Employee("王武",35,4567.90),
            new Employee("王二",45,9090.90),
            new Employee("李四",34,567.90),
            new Employee("小平",18,9090.90)
    );
    @Test
    public void test1(){
        List<String> list = Arrays.asList("ccc","aaa","bbb","ddd");
        list.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("--------");
        employees.stream()
                .sorted((x,y)->{
                    if (x.getAge()==y.getAge()){
                        return -x.getName().compareTo(y.getName());
                    }else {
                        return Integer.compare(x.getAge(),y.getAge());
                    }
                })
                .forEach(System.out::println);

     }
}

stream查找与匹配
package com.java8.demo.stream;

import com.java8.pojo.Employee;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class TestStreamAPI5 {
    /**
     *  查找与匹配
     * allMatch——检查是否匹配所有元素
     * anyMatch——检查是否至少匹配一个元素
     * noneMatch——检查是否没有匹配的元素
     * findFirst——返回第一个元素
     * findAny——返回当前流中的任意元素
     * count——返回流中元素的总个数
     * max——返回流中最大值
     * min——返回流中最小值
     */
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90, Employee.Status.FREE),
            new Employee("张三",34,9090.90, Employee.Status.FREE),
            new Employee("张三",18,9090.90, Employee.Status.VOCATION),
            new Employee("王武",35,4567.90, Employee.Status.FREE),
            new Employee("王二",45,9090.90, Employee.Status.FREE),
            new Employee("李四",34,567.90, Employee.Status.FREE),
            new Employee("小平",18,9090.90,Employee.Status.VOCATION)
    );
    @Test
    public void test1(){
        boolean b = employees.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);
        boolean b1= employees.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        boolean b2= employees.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        Optional<Employee> op = employees.stream()
                .sorted((x, y) -> Double.compare(x.getSalary(), y.getSalary()))
                .findFirst();
        System.out.println(op.get());
        Optional<Employee> any = employees.parallelStream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(any.get());
    }
    @Test
    public void test2(){
        long count = employees.stream()
                .count();
        System.out.println(count);
        Optional<Employee> max = employees.stream()
                .max((x, y) -> x.getName().compareTo(y.getName()));
        System.out.println(max.get());

        Optional<Integer> min = employees.stream()
                .map(Employee::getAge) // 通过map把工资先提取出来,再从工资中提取出来最小的
                .min(Double::compare);
        System.out.println(min.get());
    }
}
stream归约与收集
 package com.java8.demo.stream;

import com.java8.pojo.Employee;
import org.junit.Test;

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

public class TestStreamAPI6 {
    /**
     * 归约
     *  reduce(T identity, BinaryOperator) / reduce(BinaryOperator) --可以将流中元素反复结合起来,得到一个值
     * 收集
     *   collect---将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法

     */
    List<Employee> employees = Arrays.asList(
            new Employee("张三",18,9090.90, Employee.Status.FREE),
            new Employee("张三",34,9090.90, Employee.Status.FREE),
            new Employee("张三",18,9090.90, Employee.Status.VOCATION),
            new Employee("王武",35,4567.90, Employee.Status.FREE),
            new Employee("王二",45,9090.90, Employee.Status.FREE),
            new Employee("李四",34,567.90, Employee.Status.FREE),
            new Employee("小平",18,9090.90,Employee.Status.VOCATION)
    );
    @Test
    public void test1(){
        List<Integer> list = Arrays.asList(1,1,1,1);
        Integer i = list.stream()
                .reduce(0, (x, y) -> x * y); // 参数identity作为起始值x,
        System.out.println(i);
        System.out.println("-------- ");
        Optional<Integer> sum = employees.stream()
                .map(Employee::getAge)
                .reduce(Integer::sum);
        System.out.println(sum.get());
    }
    @Test
    public void test2(){
        List<Integer> list = employees.stream()
                .map(Employee::getAge)
                .collect(Collectors.toList());
        System.out.println(list);
        list.forEach(System.out::println);

        HashSet<Integer> collect = employees.stream()
                .map(Employee::getAge)
                .collect(Collectors.toCollection(HashSet::new));
        System.out.println(collect);

        // 总数
        Long collect1 = employees.stream()
                .collect(Collectors.counting());
        System.out.println(collect1);
        Double collect2 = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(collect2);
        IntSummaryStatistics collect3 = employees.stream()
                .collect(Collectors.summarizingInt(Employee::getAge));
        System.out.println(collect3);
        System.out.println(collect3.getAverage());
        Integer collect4 = employees.stream()
                .collect(Collectors.summingInt(Employee::getAge));
        System.out.println(collect4);
        // 分组
        Map<Employee.Status, List<Employee>> collect5 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(collect5);
        // 多级分组
        Map<Employee.Status, Map<String, List<Employee>>> collect6 = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((employee) -> {
                    if (employee.getAge() <= 35) {
                        return "青年";
                    } else if (employee.getAge() <= 50) {
                        return "中年";
                    } else {
                        return "老年";
                    }
                })));
        System.out.println(collect6);
    }
    // 分区
    @Test
    public void test3(){

        Map<Boolean, List<Employee>> collect = employees.stream()
                .collect(Collectors.partitioningBy((e) -> e.getAge() > 30));
        System.out.println(collect);
    }
    @Test
    public void test4(){

        String collect = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining());
        System.out.println(collect);
        String collect1 = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(","));
        System.out.println(collect1);
        String collect2 = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(",","===","=="));
        System.out.println(collect2);
    }
}
stream练习
package com.java8.demo.stream;

import com.java8.pojo.Trader;
import com.java8.pojo.Transaction;
import org.junit.Before;
import org.junit.Test;

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

public class TestTransaction {

    List<Transaction> transactions = null;

    @Before
    public void before(){
        Trader raoul = new Trader("Raoul","Cambridge");
        Trader mario = new Trader("Mario","Milan");
        Trader alan = new Trader("Alan","Cambridge");
        Trader brain = new Trader("Brain","Cambridge");

         transactions = Arrays.asList(
                new Transaction(brain, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );
    }

    // 1. 找出2011年发生的所有交易,并按交易额排序(从低到高)
    @Test
    public void test1(){

        transactions.stream()
                .filter((t) -> t.getYear()==2011)
                .sorted((e1,e2)-> Integer.compare(e1.getValue(),e2.getValue()))
                .forEach(System.out::println);

    }

    // 2。交易员都在哪些不同的城市工作过
    @Test
    public void test2(){

        transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getCity)
                .distinct()
                .forEach(System.out::println);
        transactions.stream()
                .map((t)->t.getTrader().getCity())
                .distinct()
                .forEach(System.out::println);
    }

    // 3。查找所有来自剑桥的交易员,并按姓名排序
    @Test
    public void test3(){

        transactions.stream()
                .map(Transaction::getTrader)
                .filter((s) -> s.getCity().equals("Cambridge"))
                .sorted((x,y)->x.getName().compareTo(y.getName()))
                .distinct()
                .forEach(System.out::println);

    }

    // 4。返回所有交易员的姓名字符串,按字母顺序排序
    @Test
    public void test4(){

        transactions.stream()
                .map(Transaction::getTrader)
                .map(Trader::getName)
                .sorted((x,y)->x.compareTo(y))
                .forEach(System.out::println);

        System.out.println("-----------------");
        String str = transactions.stream()
                .map((t) -> t.getTrader().getName())
                .sorted()
                .reduce("", String::concat);
        System.out.println(str);

        System.out.println("-----------------");
        transactions.stream()
                .map((t)->t.getTrader().getName())
                .flatMap(TestTransaction::filterCharacter)
                .sorted()
                .forEach(System.out::println);
    }
    public static Stream<Character> filterCharacter(String str){
        List<Character> list = new ArrayList<>();
        for (char c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }
    // 5。有没有交易员是在米兰工作的?
    @Test
    public void test5(){
        boolean b = transactions.stream()
                .map(Transaction::getTrader)
                .anyMatch((e) -> e.getCity().equals("Milan"));

        System.out.println(b);

    }
    // 6。打印生活在剑桥的交易员的所有交易额
    @Test
    public void test6(){
        Optional<Integer> cambridge = transactions.stream()
                .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
                .map(Transaction::getValue)
                .reduce(Integer::sum);
        System.out.println(cambridge.get());
    }

    // 7.所有交易中,最高的交易是多少
    @Test
    public void test7(){
        Optional<Integer> max = transactions.stream()
                .map(Transaction::getValue)
                .max(Integer::compareTo);
        System.out.println(max.get());
    }
    // 8。 找到交易额最小的交易
    @Test
    public void test8(){
        Optional<Transaction> min = transactions.stream()
                .min((x, y) -> Integer.compare(x.getValue(), y.getValue()));
        System.out.println(min.get());
    }
}

并行流和串行流

optional容器类

接口中的默认方法与静态方法

接口中的默认方法:
接口默认方法的“类优先”原则
若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时

  • 选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略。
  • 接口冲突。如果一个父接口提供方一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突。

日期时间API

package com.java8.date;

import org.junit.Test;
import java.time.*;
import java.util.Date;

public class TestLocalDateTime {
    // LocalDate、LocalTime、LocalDateTime
    @Test
    public void test1(){
        Date date = new Date();
        System.out.println(date);

        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);
        LocalDateTime localDateTime = LocalDateTime.of(2015, 03, 10, 13, 04, 34);
        System.out.println(localDateTime);
        System.out.println(localDateTime.plusDays(2));
        System.out.println(localDateTime.getYear());
    }
    // Instant:时间戳(以Unix元年:1970年1月1日 00:00:00到某个之间的毫秒值)
    @Test
    public void test2(){
        Instant ins = Instant.now();
        System.out.println(ins);
        OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
        System.out.println(odt);
        System.out.println(ins.toEpochMilli());
        Instant instant = Instant.ofEpochSecond(1);
        System.out.println(instant);
    }

    // Duration:计算两个"时间"之间的间隔
    // Period:计算两个"日期"之间的间隔
    @Test
    public void test3(){
        Instant ins = Instant.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Instant ins2 = Instant.now();
        Duration duration = Duration.between(ins, ins2);
        System.out.println(duration);
        System.out.println(duration.getSeconds());
        System.out.println(duration.toMillis());
        System.out.println("--------");

        LocalTime lt = LocalTime.now();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LocalTime lt2 = LocalTime.now();
        Duration duration2 = Duration.between(lt, lt2);
        System.out.println(duration2);
    }
}

时间校正器
// 时间校正器
    @Test
    public void test4(){
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        LocalDateTime ldt1 = ldt.withDayOfMonth(10);
        System.out.println(ldt1);

        LocalDateTime ldt2 = ldt.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
        System.out.println(ldt2);

        // 自定义:下一个工作日
        LocalDateTime ldt5 = ldt.with((l) -> {
            LocalDateTime ldt4 = (LocalDateTime) l;
            DayOfWeek dow = ldt4.getDayOfWeek();
            if (dow.equals(DayOfWeek.FRIDAY)) {
                return ldt4.plusDays(3);
            } else if (dow.equals(DayOfWeek.SATURDAY)) {
                return ldt4.plusDays(2);
            } else {
                return ldt4.plusDays(1);
            }
        });
        System.out.println(ldt5);
    }
DateTimeFormatter: 格式化时间/日期
// DateTimeFormatter: 格式化时间/日期
    @Test
    public void test5(){
        DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
        DateTimeFormatter dtf1 = DateTimeFormatter.ISO_DATE;
        LocalDateTime ldt = LocalDateTime.now();
        String format = ldt.format(dtf);
        System.out.println(format);
        String format1 = ldt.format(dtf1);
        System.out.println(format1);

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

        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        String strDate = dtf2.format(ldt);
        System.out.println(strDate);
        System.out.println("-------");
//        LocalDateTime newDate = ldt.parse(strDate, dtf2);
//        System.out.println(newDate);
    }

重复注解与类型注解

package com.java8.annotation;

import com.java8.service.MyAnnotation;
import org.junit.Test;
import java.lang.reflect.Method;

/**
 * 重复注解与类型注解
 */
public class TestAnnotation {

    @Test
    public void test1() throws NoSuchMethodException {
        Class<TestAnnotation> clazz = TestAnnotation.class;
        Method m1 = clazz.getMethod("show");
        MyAnnotation[] mas = m1.getAnnotationsByType(MyAnnotation.class);
        for (MyAnnotation ma : mas) {

            System.out.println(ma.value());
        }
    }
    @MyAnnotation("Hello")
    @MyAnnotation("world")
    public void show(){
    }
}

package com.java8.service;

import org.springframework.stereotype.Component;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;

@Repeatable(MyAnnotations.class)
@Target({TYPE,METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyAnnotation {
    String value() default "java8";
}
package com.java8.service;

import org.springframework.stereotype.Component;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;

@Target({TYPE,METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyAnnotations {
    MyAnnotation[] value();
}

你可能感兴趣的:(Java8新特性-Lambda表达式-Stream API等(学习笔记))