Java8特性Stream


参考博客: Java8新特性-尚硅谷笔记

一、Lambda

1.1 匿名函数

​ Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升。

1.2 Java内置四大核心函数式接口Consumer

Consumer 消费型接口
Supplier 提供型接口
Function<T, R> 函数型接口
Predicate 断言型接口

1.3方法引用

对象 :: 实例方法
类 :: 静态方法
类 :: 实例方法
注意:Lambda 表达实体中调用方法的参数列表、返回类型必须和函数式接口中抽象方法保持一致

二、Stream开始

参考:置IntelliJ IDEA支持lambda表达式

Stream是数据渠道,用于操作数据源(集合和数组等),集合讲的是数据,流讲的是计算。
Stream自己不会存储元素
Stream不会改变源对象,会返回一个持有结果的新Stream
Stream操作是延迟的,这意味着会等到需要结果的时候才执行

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

1. 流的常用创建方法

1.1 使用Collection下的 stream() 和 parallelStream() 方法
1.2创建流的几种方法

/**
* 创建流
*/
@Test
public void test01(){
    /**
    * 集合流
    *  - Collection.stream() 穿行流
    *  - Collection.parallelStream() 并行流
    */
    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();

    //数组流
    //Arrays.stream(array)
    String[] strings = new String[10];
    Stream<String> stream2 = Arrays.stream(strings);

    //Stream 静态方法
    //Stream.of(...)
    Stream<Integer> stream3 = Stream.of(1, 2, 3);

    //无限流
    //迭代
    Stream<Integer> stream4 = Stream.iterate(0, (i) -> ++i+i++);
    stream4.forEach(System.out::println);

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

2.流的中间操作

2.1 筛选与切片

filter:过滤流中的某些元素
limit(n):获取n个元素
skip(n):跳过n元素,配合limit(n)可实现分页
distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素

2.2 map映射

map:映射每个元素,如.mapToInt(),.mapToDouble(),如果元素为NULL会抛空指针异常。
可以在数据库设置字段非空,可以使用filter过滤元素
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

2.3 排序

     <code> sorted():自然排序,流中元素需实现Comparable接口</code>
    sorted(Comparator com):定制排序,自定义Comparator排序器  

2.4 消费

    peek:如同于map,能得到流中的每一个元素。但map接收的是一个Function表达式,有返回值;而peek接收的是Consumer表达式,没有返回值。

3.流的终止操作

3.1 匹配、聚合操作

    findFirst:返回流中第一个元素
    findAny:返回流中的任意元素
    count:返回流中元素的总个数
    max:返回流中元素最大值
    min:返回流中元素最小值

3.2 规约操作

归约:reduce(T identity, BinaryOperator) / reduce(BinaryOperator) 可以将流中的数据反复结合起来,得到一个值

/**
* Java:
*  - reduce:需提供默认值(初始值)
* Kotlin:
*  - fold:不需要默认值(初始值)
*  - reduce:需提供默认值(初始值)
*/
@Test
public void test01(){
    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
    Integer integer = list.stream()
        .reduce(0, (x, y) -> x + y);
    System.out.println(integer);
}

3.3 收集操作

collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。

3.4 Collector 工具库:Collectors
Collectors类实现了很多归约操作,例如将流转换成集合和聚合元素。
Collectors.toMap,把流所有的元素收集到一个Map,其键和值是将所提供的映射函数应用于输入元素的结果。
Collectors.toList(),把流所有的元素收集到一个List
Collectors.joining(", "),把流所有的元素以逗号连接到一个字符串

4.并行流 / 串行流

底层基于:Fork/Join实现框架

@Test
public void test03(){
    //串行流(单线程):切换为并行流 parallel()
    //并行流:切换为串行流 sequential()
    LongStream.rangeClosed(0, 100000000L)
        .parallel() //底层:ForkJoin
        .reduce(0, Long::sum);

}

5.Optional类

Optional.of(T t):创建一个 Optional 实例
Optional.empty(T t):创建一个空的 Optional 实例
Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则空实例
isPresent():判断是否包含某值
orElse(T t):如果调用对象包含值,返回该值,否则返回 t
orElseGet(Supplier s):如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f):如果有值对其处理,并返回处理后的 Optional,否则返回 Optional.empty()
flatmap(Function mapper):与 map 相似,要求返回值必须是 Optional

6.Java8接口中允许实现默认方法

接口中定义了一个默认方法,另外一个父类或者接口中又定义了一个同名方法。默认类优先

三、实践使用

参考【好】:Java 8 stream的详细用法
参考【好】:JDK1.8新特性Stream和Collectors19个常用示例总结

参考:Java8新特性之forEach+Lambda 表达式遍历Map和List

参考【好】:java 8 lambda表达式list操作分组、过滤、求和、最值、排序、去重
1.分组
2.过滤
3.求和
4.最值
5.List 转map
6.排序
7.去重
8.获取list某个字段组装新list
9.批量设置list列表字段为同一个值
10.不同实体的list拷贝

1.分组、求和(最大、最小、平均值)、map组装新list

参考:java8 list统计(求和、最大、最小、平均)

//初始化
List<User> list = new ArrayList<User>();
list.add(new User("用户1", 1, 160.1, new BigDecimal("160.1")));
list.add(new User("用户1", 100, 160.2, new BigDecimal("160.1")));
list.add(new User("用户2", 10, 160.2, new BigDecimal("160.1")));
list.add(new User("用户2", 11, 160.2, new BigDecimal("160.1")));
list.add(new User("用户3", 18, 20.1, new BigDecimal("160.1")));
list.add(new User("用户3", 11, 10.1, new BigDecimal("160.1")));
list.add(new User("用户3", 12, 10.8, new BigDecimal("160.2")));

//分组求和Integer、Double、BigDecimal,返回Map格式
DecimalFormat df = new DecimalFormat("0.0");
Map<String,List<User>> groupMap = list.stream().collect(Collectors.groupingBy(User::getName));
Map<String,User> resultMap = new HashMap<>();
groupMap.forEach((k,v)->{
    User dto = new User();
    //Integer求和
    dto.setAge(v.stream().mapToInt(User::getAge).sum());
//            dto.setAge(v.stream().filter(x -> null!=x.getAge()).mapToInt(User::getAge).sum());
//            dto.setAge(v.stream().mapToInt(x -> Convert.toInt(x.getAge(), 0)).sum());
    //Double求和
    dto.setHeight(Double.valueOf(df.format(v.stream().mapToDouble(User::getHeight).sum())));
    //BigDecimal求和
    dto.setDecimal(v.stream().map(User::getDecimal).reduce(BigDecimal.ZERO, BigDecimal::add));
    resultMap.put(k, dto);

    //测试最大、最小、平均值【以给默认值0的方式去空,有空时最小值会=0】
    Integer maxAge = v.stream().mapToInt(x -> Convert.toInt(x.getAge(),0)).max().getAsInt();
    Integer minAge = v.stream().mapToInt(x -> Convert.toInt(x.getAge(),0)).min().getAsInt();
    //2种方式平均值,目标是Integer时,sum()/v.size()会转int丢失小数部分
    Double avgAge = Double.valueOf(df.format((v.stream().mapToInt(x -> Convert.toInt(x.getAge(),0)).average().getAsDouble())));
    Double avgAge2 = Double.valueOf(df.format((v.stream().mapToInt(x -> Convert.toInt(x.getAge(),0)).sum()/v.size())));

    Double avgHeight = Double.valueOf(df.format((v.stream().mapToDouble(User::getHeight).average().getAsDouble())));
    Double avgHeight2 = Double.valueOf(df.format((v.stream().mapToDouble(User::getHeight).sum()/v.size())));
});

//获取list某个字段组装新list
List<String> names = list.stream().map(x -> x.getName()).collect(Collectors.toList());
List<Integer> ages = list.stream().map(x -> x.getAge()).collect(Collectors.toList());

2.排序,自定义过滤

参考:java8新特性stream,按照某个字段排序,以及取出前几条数据

//.reversed()倒序排序,去掉.reversed()正序排列
list = list.stream().sorted(Comparator.comparing(ExamGrades1::getYear).reversed()).collect(Collectors.toList());
//按照num倒叙排列并且取出前两条数据
List<ViewStoreStockLib> collect = libs2.stream().sorted(Comparator.comparing(ViewStoreStockLib::getNum).reversed()).limit(2).collect(Collectors.toList());

//自定义过滤:不等于name
public static boolean filterName(String name, User user) {
    if(!StrUtil.equals(name, user.getName())) {
        return true;
    }
    return false;
}

//过滤:name不等于用户1
List<User> resultList = list.stream().filter(x -> !StrUtil.equals("用户1", x.getName())).collect(Collectors.toList());
List<User> resultList2 = list.stream().filter(x -> TestSen.filterName("用户1", x)).collect(Collectors.toList());

3.合并list,去重,分页,排序

参考:Java8 stream 根据对象字段去重
参考:No value present 异常处理

List<List<UserInfo>> collect = new ArrayList<>();
省略...
collect.add(list1);
collect.add(list2
//合并
List<UserInfo> noUniqueList = collect.stream().flatMap(l -> l.stream()).collect(Collectors.toList());

//如果主持人不存在
boolean flag = noUniqueList.stream().filter(x -> StrUtil.equals(lecture.getTrainUser(), x.getId())).findAny().isPresent();
if(!flag) {
    UserInfo o = lectureMapper.getUserByid(lecture.getTrainUser());
    noUniqueList.add(o);
}

//使用TreeSet去重
List<UserInfo> unique1 = noUniqueList.stream().collect(
        Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getId()))),
                ArrayList::new));

//如果集合中不存在元素,.get()会报错No value present
Optional<SelfGrades> optional = gradesList1.stream().filter(x -> StrUtil.equals(x.getPersonId(), planUser.getUserId())).findAny();
SelfGrades o = optional.isPresent() ? optional.get() : null;



//分页
public static <T> List<T> paging(List<T> list, int page, int limit) {
    List<T> result = list.stream()
            .skip((page - 1) * limit)
            .limit(limit)
            .collect(Collectors.toList());
    return result;
}

//如果集合中有一个元素满足条件就返回true
boolean flag = list.stream().anyMatch(x -> x.getQuarterlyCode()==quaCode && StrUtil.equals(x.getOrganCode(), orgCode));

//将多个集合中的元素合并成一个集合
List<NetProgressVo> pageList = Stream.of(list, list2).flatMap(x -> x.stream()).collect(Collectors.toList());

//过滤搜索,是否网报
int noFilterCount = pageList.size();//是否网报过滤前总count
if(!StrUtil.isBlank(rest.getReportStatus())) {
    pageList = pageList.stream().filter(x -> StrUtil.equals(x.getReportStatus(), rest.getReportStatus())).collect(Collectors.toList());
}

//.reversed()倒序排序,去掉.reversed()正序排列
pageList = pageList.stream().sorted(Comparator.comparing(NetProgressVo::getQuarterlyCode).reversed()).collect(Collectors.toList());
int allCount = pageList.size();//分页前总count
//分页查询
List<NetProgressVo> resList = MonitorService.paging(pageList, rest.getPage(), rest.getLimit());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值