Java并发JUC(六)

682 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情


本文主要介绍四大函数式接口及Stream流相关知识,你如果还不懂Stream及函数式接口的,就快来看快来学...

12. 四大函数式接口

函数式接口:只有一个方法的接口。接口上面会有@FunctionalInterface注解。

四大函数式接口:Consumer、Function、Predicate、Supplier。

Function函数式接口

只要是函数型接口,都能用lambda表达式进行简化。

Function函数型接口,有一个输入参数,有一个输出。

下面这个示例的功能就是输入什么返回什么。

public static void main(String[] args) {
  //就写了个工具类
  Function function = new Function<String,String>() {
    @Override
    public String apply(String str) {
      return str;
    }
  };
}

lambda简化:

    public static void main(String[] args) {
        Function<String,String> function = (str)->{
            return str;
        };
        System.out.println(function.apply("asd"));//结果输出asd
    }

Predicate函数型接口,这是一个断定型的函数式接口,有一个输入参数,返回值只能是布尔值。

当然下面这个也是可以用lambda简化的。

    public static void main(String[] args) {
        //判断字符串是否为空
        Predicate<String> predicate = new Predicate<String>() {
            @Override
            public boolean test(String str) {
                return str.isEmpty();
            }
        };
        System.out.println(predicate.test(""));//结果输出true
    }

Consumer消费型函数式接口,只有输入没有返回值。其中foreach传入的就是这个消费型函数式接口。

public static void main(String[] args) {
    Consumer<String> consumer = new Consumer<String>() {
        @Override
        public void accept(String str) {
            System.out.println(str);
        }
    };
       //打印字符串
      consumer.accept("adasda");//结果输出adasda
}

Supplier供给型函数式接口,没有参数只有返回值。

    public static void main(String[] args) {
        //lambda简化
        Supplier<Integer> supplier = ()->{
            System.out.println("get()");
            return 1024;
        };
        System.out.println(supplier.get());//结果输出get()  1024
    }

这就是四大函数式接口。再次强调:只要是函数式接口都可以用lambda表达式来简化。

13. Stream流式计算

什么是Stream流式计算

大数据包含存储+计算。像集合、MySQL这些本质都是用来存储的东西,计算是要交给流来操作的。

list转stream流:list.stream()

  • filter:过滤,就是过滤器,符合条件的通过,不符合条件的过滤掉
// 筛选出成绩不为空的学生人数
count = list.stream().filter(p -> null != p.getScore()).count();
  • map:映射,他将原集合映射成为新的集合,在VO、PO处理的过程中较常见。
// 取出所有学生的成绩
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
​
// 将学生姓名集合串成字符串,用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
  • sorted:排序,可以根据指定的字段进行排序
// 按学生成绩逆序排序 正序则不需要加.reversed()
filterList = list.stream().filter(p -> null != p.getScore()).sorted(Comparator.comparing(UserPo::getScore).reversed()).collect(Collectors.toList());
  • forEach: 这个应该是最常用的,也就是为每一个元素进行自定义操作
  • collect:聚合,可以用于GroudBy按指定字段分类,也可以用于返回列表或者拼凑字符串
// 返回list
List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
// 返回string用逗号分隔
String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
  • statistics:统计,可以统计中位数,平均值,最大最小值
DoubleSummaryStatistics statistics = filterList.stream().mapToDouble(p -> p.getScore()).summaryStatistics();
System.out.println("列表中最大的数 : " + statistics.getMax());
System.out.println("列表中最小的数 : " + statistics.getMin());
System.out.println("所有数之和 : " + statistics.getSum());
System.out.println("平均数 : " + statistics.getAverage());
  • parallelStream:并行流,可以利用多线程进行流的操作,提升效率。但是其不具备线程传播性,因此使用时需要充分评估是否需要用并行流操作
// 并行流
count = list.parallelStream().filter(p -> null != p.getScore()).count();

下面看案例与要求:

/**
 * 题目要求:一分钟内完成此题,只能用一行代码实现!
 * 现在有五个用户!筛选:
 * 1、ID必须是偶数
 * 2、年龄必须大于23
 * 3、用户名转为大写字母
 * 4、用户名字母倒着排序
 * 5、只输出一个用户!
 */
public class Test {
    public static void main(String[] args) {
        User u1 = new User(1,"a",21);
        User u2 = new User(2,"b",22);
        User u3 = new User(3,"c",23);
        User u4 = new User(4,"d",24);
        User u5 = new User(6,"e",25);
        //集合就是存储
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
        //计算交给stream流
        //链式编程
        list.stream()
                .filter((u)->{return u.getId()%2==0;})
                .filter(u->{return u.getAge() > 23;})
                .map(u->{return u.getName().toUpperCase();})
                .sorted((uu1,uu2)->{return uu2.compareTo(uu1);})
                .limit(1)
                .forEach(System.out::println);
    }
}