Strame--流操作

在工作中用的Stream操作用的地方还比较多,现在从下面记录一下

通常情况下在记录的过程中需要进行多个List的调整和记录,所有需要对Stream流的所有API都熟练掌握,避免有时候进行记不全的情况。

Stream流的操作及方法汇总

方法   作用
filter()  接收lambda,从流中排除某些操作

limit() 截断流,使其元素不超过给定对象

skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补

distinct 筛选,通过流所生成元素的hashCode()和equals去除重复元素

map 接受Lambda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素

sorted() 自然排序(Comparable)
sorted(Comparator com) 定制排序(Comparator)

allMatch 检查是否匹配所有元素

anyMatch 检查是否至少匹配一个元素

noneMatch 检查是否没有匹配所有元素

findFirst 返回第一个元素
findAny 返回当前流中的任意元素
count 返回流中元素的总个数
max 返回流中最大值
min 返回流中最小值
reduce 归约操作可以将流中元素反复结合起来,得到一个值
collect 将流转换为其他形式,接收一个Collector接口实现,用于给Stream中汇总的方法

public static void main(String[] args) {
        List<User> list = getUserList();
        list.stream().forEach(user -> System.out.println("id:"+user.getId()+",姓名:"+user.getName()+",年龄:"+user.getAge()));
        //getFilter(list);
        //getSkipLimit(list);
        //getDistinct(list);
        //;
        //Stream<User> stream =  list.stream().sorted();
        //reduce和max和min
        System.out.println(list.stream().map(User::getAge).reduce(1000,Integer::sum));
        System.out.println(list.stream().map(User::getAge).max(Integer::compare).get());
        System.out.println(list.stream().map(User::getAge).min(Integer::compare).get());
    }


    private static void  getFindFirstAndFindAny(List<User> list){
        //User userModel  =  list.stream().filter( user -> user.getAge()>500&&user.getAge()<1000).findFirst().get(null);
        //orElse如果流中没有数据就返回空
        User userModel  =  list.stream().filter( user -> user.getAge()>500&&user.getAge()<1000).findAny().orElse(null);
        System.out.println(userModel.toString());
    }
    private static void getMath(List<User> list){

        //这里使用Age做匹配
        //allMatch是否所有数据都满足500<age<1000

        //anyMatch 查看是否有一条数据是


        //noneMatch 所有数据都不满足

        Boolean bl  = list.stream().anyMatch(user -> user.getAge()>500&&user.getAge()<1000);
        System.out.println(bl);
        if(bl){
            list.stream().filter(user -> user.getAge()>500&&user.getAge()<1000).forEach(user -> System.out.println(user.toString()));
        }

    }

    //sorted和map
    private static void getSortedAndMap(List<User> list){
        Stream<Object> stream  = list.stream().sorted(Comparator.comparing(User::getAge).reversed()).map(user -> user.getName());
        stream.forEach(user -> System.out.println(user.toString()));

    }
    private static void getDistinct(List<User> list){
        //去重
        Stream<User> stream = list.stream().distinct();
        stream.forEach(user -> System.out.println(user.getName()));
    }

    private static void  getSkipLimit(List<User> list){
        //skip() 和 limit()
        /**
         * 单用limit的话就是从第0个开始
         * skip也是从0开始
         */
        Stream<User> stream = list.stream().skip(4).limit(3);
        stream.forEach(user -> System.out.println(user.getName()));
    }
    public static void getFilter( List<User> list){
        //filter()排除
        //forEach循环便利
        list.stream().filter(user -> !user.getAge().equals("170")).forEach(user -> System.out.println(user.getName()));
        System.out.println("======================================");
        //这两个相等
        Stream<User> stream = list.stream().filter(user -> !user.getAge().equals("170"));
        stream.forEach(user -> System.out.println(user.getName()));
    }

    //
    public static List<User> getUserList(){
        User user = new User(""+((int)(Math.random()*1000000000)+1000000),"李白",1000);
        User user1 = new User(""+((int)(Math.random()*1000000000)+1000000),"周树人",170);
        User user2 = new User(""+((int)(Math.random()*1000000000)+1000000),"白居易",900);
        User user3 = new User(""+((int)(Math.random()*1000000000)+1000000),"林则徐",780);
        User user4 = new User(""+((int)(Math.random()*1000000000)+1000000),"赵亦",970);
        User user5 = new User(""+((int)(Math.random()*1000000000)+1000000),"卫东来",1100);

        List<User> list = new ArrayList<>();
        list.add(user);
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        list.add(user5);

        return list;
    }

下面主要介绍Stream的每个用法的主要介绍:

判断大于小于使用,这个时候,是要通过map先取值,然后再进行比大小通过max,min 

//使用Straem流判断取值判断
list.stream().map(User::getAge).max(Integer::compare).get(); //比较大于
list.stream().map(User::getAge).min(Integer::compare).get();//比较小于

过滤操作,则是先通过filter进行过滤然后再通过查询操作

        User userModel  =  list.stream().filter( user -> user.getAge()>500&&user.getAge()<1000).findAny().orElse(null);

垂直执行:map和filter

先看下面一个例子,找出流中"b"的字符串,并将其转化为大写,包含两个中间操作 map 和 filter 以及结束操作forEach。

如果我们改变操作顺序,filter方法最先执行,将大大减少执行的次数。

水平执行:sorted

接下来,我们看下sorted排序操作,现学现卖,咱们把filter放在了map操作之前:

 

 

我们再一次更改操作顺序,来尝试优化性能:

这次发现,sorted方法并没有被调用,因为被filter过滤之后,流中只剩下一个元素,也就不需要执行排序操作了。

而且,sorted对filter和map这种垂直执行的方法,具有截断作用,也就是说sorted前的中间操作,需要完全执行,形成一个完整的Stream流,交给sorted排序。

 举个例子,比如把"b"和"d"过滤出来,转为大写,并排序:

 因为sorted的截断作用,先垂直执行filter和map,然后水平执行sorted,最后垂直执行forEach。

下面是Stream的高级操作

Collectors接口中方法的实现决定了如何对流执行收集操作(如搜集到List、Set、Map)。
toList:把流中元素收集到List
toSet:把流中元素收集到Set
toCollection:把流中元素收集到创建的集合
counting:计算流中元素的个数
summingInt:对流中元素的整数属性求和
averagingInt:计算流中元素Integer属性的平均值
summarizingInt:收集流中Integer属性的统计值
joining:连接流中的每个字符串
maxBy:根据比较器选择最大值
minBy:根据比较器选择最小值
reducing:从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而规约成单个值
collectingAndThen:包裹另一个收集器,对其结果转换函数
groupingBy:根据某个属性值对流分组,属性为K,结果为V
partitioningBy:根据true、false进行分区
 

package com.zyp.test;

import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModelProperty;
import jdk.internal.dynalink.linker.LinkerServices;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

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


public class StreamPlus {
    public static void main(String[] args) {
        Person p1=new Person(1, "1", "男", 18,"一年级");
        Person p2=new Person(2, "2", "女", 17,"二年级");
        Person p3=new Person(3, "3", "男", 18,"三年级");
        Person p4=new Person(4, "2", "女", 19,"二年级");
        Person p5=new Person(5, "1", "男", 20,"一年级");
        Person p6=new Person(6, "3", "男", 18,"三年级");
        List<Person> lists= Lists.newArrayList(p1,p2,p3,p4,p5,p6);
        //遍历输出
        lists.stream().forEach(p-> System.out.println(p));
        System.out.println("------------------------------");
        //根据年龄排序,默认升序,reversed()逆序输出
        lists.stream().sorted(Comparator.comparing(Person::getAge,Integer::compareTo).reversed()).forEach(s-> System.out.println(s));
        System.out.println("------------------------------");
        //输出性别为女并且年龄大于18
        lists.stream().filter(person -> StringUtils.equals(person.getSex(),"女") && person.getAge()>18).forEach(p-> System.out.println(p));
        System.out.println("------------------------------");
        //分别输出年龄大于18和小于等于18的年龄总和
        lists.stream().collect(Collectors.partitioningBy(p->p.getAge()>18,Collectors.summingInt(Person::getAge))).forEach((K,V)->{
            System.out.println((K?"大于18":"小于等于18")+"的年龄总和"+V);
        });
        System.out.println("------------------------------");
        //根据性别分组
        lists.stream().collect(Collectors.groupingBy(Person::getSex)).forEach((K,V)->{
            System.out.println(K+"的有"+V);
        });
        //根据性别和年级分组
        System.out.println("------------------------------");
        lists.stream().collect(Collectors.groupingBy(person -> person.getClass1()+"年级"+person.getSex())).
                forEach((K,V)->System.out.println(K+"的有"+V));
        //统计男女总数
        System.out.println("------------------------------");
        lists.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.counting())).forEach((K,V)->{
            System.out.println(K+"有"+V+"个");
        });
        //统计男女年龄
        System.out.println("------------------------------");
        //对流中元素的整数属性求和
        //方式1
        lists.stream().collect(Collectors.groupingBy(Person::getSex,Collectors.summingInt(Person::getAge))).forEach((K,V)->{
            System.out.println(K+"总年龄为"+V);
        });
        //收集流中Integer属性的统计值
        //方式2
        System.out.println("------------------------------");
        lists.stream().collect(Collectors.groupingBy(Person::getSex,Collectors.summarizingInt(Person::getAge))).forEach((K,V)->{
            System.out.println(K+"总年龄为"+V.getSum());
        });
        //统计每个年级男女的年龄的和
        System.out.println("------------------------------");
        lists.stream().collect(
                Collectors.groupingBy(person -> person.getClass1()+person.getSex()+"的",
                        Collectors.summingInt(Person::getAge))).forEach((K,V)->
            System.out.println(K+"总年龄为"+V)
        );
        System.out.println("------------------------------");
        //获取每个年级年龄最大的人
        lists.stream().collect(Collectors.groupingBy(Person::getClass1,
                Collectors.maxBy(Comparator.comparing(Person::getAge)))).forEach((K,V)->{
            System.out.println(K+"最大年龄为"+V.get().getAge());
        });
        System.out.println("------------------------------");
    }
}


@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
class Person{
    @ApiModelProperty("序号")
    private Integer id;

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("性别")
    private String sex;

    @ApiModelProperty("年龄")
    private Integer age;

    @ApiModelProperty("班级")
    private String class1;
}

其实主要对Stream进行高级操作的时候还是要结合具体的操作好具体的API进行整体的分析才可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值