Java8新特性

函数式接口

java.util.function,java内置核心四大函数式接口

image-20200901195115544

// R Function<T,R>
Function<String,Integer> function  = s -> {return s.length();};
System.out.println(function.apply("abc"));

// boolean Predicate<T>
Predicate<String> predicate = s ->{return s.isEmpty();};
System.out.println("rin");

// void Consumer<T>
Consumer<String> consumer = s -> {
System.out.println("its consumer");
};
consumer.accept("rin");

// T Supplier<T>
Supplier<String> supplier = ()->{return "supplier return";};
System.out.println(supplier.get());

Stream流式计算

Stream流

流(Stream) 到底是什么呢?

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

特点

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

如何使用

源头=>中间流水线=>结果

image-20200907215158171

  1. 创建一个Stream:一个数据源(数组、集合)
  2. 中间操作:一个中间操作,处理数据源数据
  3. 终止操作:一个终止操作,执行中间操作链,产生结果

案例:

@Data
@NoArgsConstructor
@AllArgsConstructor
class User{
    private Integer id;
    private String userName;
    private int age;
}

/**
 * 题目:请按照给出的数据,找出同时满足以下条件的用户,也即以下条件全部满足偶数ID且年龄大于24
 * 且用户名转为大写且用户字母倒排序
 * 只输出一个用户名字
 * */
public class StreamDemo {
    public static void main(String[] args) {
        User u1 = new User(11,"aa",23);
        User u2 = new User(12,"bb",28);
        User u3 = new User(13,"cc",22);
        User u4 = new User(14,"dd",28);
        User u5 = new User(16,"ee",26);

        List<User> list = Arrays.asList(u1, u2, u3, u4, u5);

        // Stream<T> filter(Predicate<? super T> predicate);  过滤器
        // <R> Stream<R> map(Function<? super T, ? extends R> mapper);  映射
        list.stream().filter(user->{return user.getId()%2==0;}) // 偶数ID 过滤器
                .filter(user -> {return user.getAge()>24;}) // 年龄大于24过滤器
                .map(u->{return u.getUserName().toUpperCase();}) // 用户名转为大写,返回值变成Steam<String>了
                .sorted((o1,o2)->{return o2.compareTo(o1);}) // 用户字母倒排序
                .limit(2) // 限制个数
                .forEach(System.out::println);
    }
}

方法引用

使用场景

我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。

方法引用的分类

类型 语法 对应的Lambda表达式
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) -> 类名.instMethod(args)
构建方法引用 类名::new (args) -> new 类名(args)