Java基础| Java8 中的 Stream,常用集锦(持续更新)

Stream简介

        Lambda表达式作为java8的新特性,早已是‘家喻户晓’,Lambda表达式使得java编程越发的简洁,提高了编程效率和可读性,Lambda表达式允许通过创建只有一个抽象方法的接口(函数式接口)的实例,本博文主要简单接收Stream的操作符,简单原理,实际应用。

操作符

       操作符顾名思义就是对数据进行的一种工作,可以是一道加工程序,也可以是具体的字符,就如工人在流水线上对产品加工产品 Stream的操作符大体上分为两种:中间操作符终止操作符

在这里插入图片描述

       中间操作符

       对于数据流来说,中间操作符在执行制定处理程序后,数据流依然可以传递给下一级的操作符。 中间操作符包含8种(排除了parallel,sequential,这两个操作并不涉及到对数据流的加工操作):

  • map(mapToInt,mapToLong,mapToDouble) 转换操作符,把比如A->B,这里默认提供了转int,long,double的操作符。

  • limit 限流操作,比如数据流中有10个 我只要出前3个就可以使用。

  • distint 去重操作,对重复元素去重,底层使用了equals方法。

  • filter 过滤操作,把不想要的数据过滤。

  • peek 挑出操作,如果想对数据进行某些操作,如:读取、编辑修改等。

  • skip 跳过操作,跳过某些元素。

  • sorted(unordered) 排序操作,对元素排序,前提是实现Comparable接口,当然也可以自定义比较器。

       终止操作符

       数据经过了中间过程的操作,会最终对所有的数据做收集和消费,数据到该节点就停止加工,终止操作符只能使用一次

  • collect 收集操作,将所有数据收集起来。
  • count 统计操作,统计最终的数据个数。
  • findFirst、findAny 查找操作,查找第一个、查找任何一个 返回的类型为Optional。
  • forEach、forEachOrdered 遍历操作,这里就是对最终的数据进行消费了。
  • toArray 数组操作,将数据流的元素转换成数组。

提示:java8专门为函数式接口提供了@FunctionalInterface注解,该注解通常放在接口定义前面,该注解对程序功能没有任何作用,他用于告诉编译器执行更严格检查–检查该接口必须是函数式接口,否则编译报错

常用集锦

       转换1

/**
 * @author dzx 
 * @since 2020/9/20
 */
public class Test {
    public static void main(String []args){
        //=====================================map()、mapToInt、mapToDouble、mapToFloat、mapToLong、toMap()===============================


        //List<S> ---> List<T> , S为User[username,sex] T为Person[sex]
        List<User> users1 = new ArrayList<>();
        users1.add(User.builder().username("dzx").sex("男").build());
        users1.add(User.builder().username("sxl").sex("女").build());
        //输出 :[Person(sex=男), Person(sex=女)]
        List<Person> people =  users1.stream().map(v->Person.builder().sex(v.getSex()).build()).collect(Collectors.toList());
        System.out.println(people);


        //List<S> --> Map<T,S> , S为User[userId,username,sex] T为userId的类型
        List<User> users2 = new ArrayList<>();
        users2.add(User.builder().userId("DZ2020").username("dzx").sex("男").build());
        users2.add(User.builder().userId("DZ2021").username("sxl").sex("女").build());
        //输出map结构 :{DZ2021=User(userId=DZ2021, username=sxl, sex=女), DZ2020=User(userId=DZ2020, username=dzx, sex=男)}
        Map<String,User> map1 = users2.stream().collect(Collectors.toMap(User::getUserId, Function.identity()));
        System.out.println(map1);
        //toMap的过程中会出现key冲突,会报Duplicate key的编译错误, 解决Key冲突:引入一个合并函数,它指出在发生冲突的情况下,我们保留现有条目或者替换
        users2.add(User.builder().userId("DZ2021").username("hxj").sex("女").build());
        //输出map结构 :{DZ2021=User(userId=DZ2021, username=hxj, sex=女), DZ2020=User(userId=DZ2020, username=dzx, sex=男)}
        Map<String,User> map2 = users2.stream().collect(Collectors.toMap(User::getUserId, Function.identity(),(exist,replace)->replace));
        System.out.println(map2);

        //List<String> --> List<Integer>
        List<Integer> ints = Stream.of("1", "2", "3").map(Integer::parseInt).collect(Collectors.toList());
        //[1, 2, 3]
        System.out.println(ints);

        //mapToInt
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToInt(String::length)
                //566125
                .forEach(System.out::print);
    }
}

       转换2

public class Test {
    public static void main(String []args){
    
       //基本类型数组->包装类型集合
        List<Integer> turnInt = Stream.of(1,2,3,4).collect(Collectors.toList());
        //集合->字符串
        String turnStr = Stream.of("156","22","18","12").collect(Collectors.joining(","));
		//156,22,18,12
        System.out.println(turnStr);


		//flatMap使用,拍平,把多个元素集合合并为一个集合
        List<List<Integer>> lists = new ArrayList<>();
        List<Integer> list1 = new ArrayList<>();
        list1.add(11);
        list1.add(22);
        List<Integer> list2 = new ArrayList<>();
        list2.add(33);
        list2.add(44);
        lists.add(list1);
        lists.add(list2);
        //[[11, 22], [33, 44]]
        System.out.println(lists);
        List<Integer> collect = lists.stream().flatMap(Collection::stream).collect(Collectors.toList());
        //[11, 22, 33, 44]
        System.out.println(collect);
    }

}

       统计(加减)

    public static void main(String []args){
        //=====================================count()、sum()、max()、min()

        //统计集合中的所有元素的总和
        List<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        Integer total1 = integers.stream().mapToInt(v->v).sum();
        System.out.println(total1);

        //最大值和最小值
        Integer total2 = integers.stream().mapToInt(v->v).max().getAsInt();
        Integer total3= integers.stream().mapToInt(v->v).min().getAsInt();
        System.out.println(total2);
        System.out.println(total3);

        //bigdecimal大数据相加
        List<BigDecimal> bigDecimalsList = new ArrayList<>();
        bigDecimalsList.add(new BigDecimal("1000"));
        bigDecimalsList.add(new BigDecimal("2000"));
        bigDecimalsList.add(new BigDecimal("3000"));
        //将user对象的mongey取出来map为Bigdecimal .map(User::getMoney)
        //使用reduce聚合函数,实现累加器  reduce 减少【表多个bigdecimal相加聚合在一起,减少了bigdecimal】
        System.out.println(bigDecimalsList.stream().reduce(BigDecimal.ZERO,BigDecimal::add));

    }

       排序

 public static void main(String []args){
        //================================sort、forEachOrdered

        //按照对象的年龄从小到大排序
        List<User> users1 = new ArrayList<>();
        users1.add(User.builder().age(12).build());
        users1.add(User.builder().age(178).build());
        users1.add(User.builder().age(1).build());
        //1(大于) 0(等于) -1(小于)
        List<User> user2 = users1.stream().sorted((x,y)->x.getAge()>y.getAge()?1:(x.getAge().equals(y.getAge()))?0:-1).collect(Collectors.toList());
        //输出[User(age=1), User(age=12), User(age=178)]
        System.out.println(user2);

        //forEachOrdered 适用用于并行流的情况下进行迭代,能保证迭代的有序性
        //输出[User(age=178), User(age=12), User(age=1)]
        users1.stream().parallel().forEachOrdered(System.out::print);
        System.out.println();
        //Comparator.comparing()
        List<User> user3 = new ArrayList<>();
        user3.add(User.builder().age(2).money(11).build());
        user3.add(User.builder().age(2).money(10).build());
        user3.add(User.builder().age(3).money(0).build());
        //默认升序排列(从小到大),按照年龄属性排序,Comparator.reverseOrder()按照从大到小排序(降序) 等同于
//        System.out.println(user3.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList()));
        System.out.println(user3.stream().sorted(Comparator.comparing(User::getAge,Comparator.reverseOrder())).collect(Collectors.toList()));
        //java.util.Collections 排序
        Collections.sort(userList, Comparator.comparingInt(User::getAge));//等效于 (x,y)->x.getAge()-y.getAge()
        System.out.println(userList);
        //先按照年龄排序,若相等则按金额排序
        System.out.println(user3.stream().sorted(Comparator.comparing(User::getAge).thenComparing(User::getMoney)).collect(Collectors.toList()));
    }

       查找&去重

public static void main(String []args){
        //==================================skip()、limit()、findAny、distinct、

        //跳过前面某些元素,输出51-48
        Stream.of(1,2,51,-48).skip(2).forEach(System.out::print);

        //只取前面几个元素,输出12
        Stream.of(1,2,51,-48).limit(2).forEach(System.out::print);

        //取任意一个
        Integer integer = Stream.of(1,2,51,-48).findAny().get();
        System.out.println(integer);
        
         //任意匹配其中之一
        boolean flag1 = Stream.of(1,2,51,-48).anyMatch(item->item>0);
        //对anyMatch取反
        boolean flag2 = Stream.of(1,2,51,-48).noneMatch(item->item>0);
        //全部匹配
        boolean flag3 = Stream.of(1,2,51,48).allMatch(item->item>0);
        //true false true
        System.out.println(flag1 +" "+flag2+" "+flag3);

        //去重,若根据userid去重,需要同时重写equals和hashcode方法
        // @Override
        //    public boolean equals(Object obj) {
        //        return ((User) obj).getUserId().equals(userId);
        //    }
        //
        //    @Override
        //    public int hashCode() {
        //        return userId.hashCode();
        //    }
        List<User> users1 = new ArrayList<>();
        users1.add(User.builder().age(12).userId("D2018").build());
        users1.add(User.builder().age(10).userId("D2020").build());
        users1.add(User.builder().age(10).userId("D2018").build());

        //根据某个字段去重
        //collectingAndThen可以理解为收集并进行下一步操作,TreeSet中放入属性的比较器,由于TreeSet是通过TreeMap的形式来去重。
        //若遇到相同的key,后者会覆盖前者,类似(exist,replace)->replace,最后通过new ArrayList(TreeSet)的构造形式取出TreeSet里的value
        List<User> users2 = users1.stream().distinct().collect(Collectors.toList());
        System.out.println(users2);
 List<User> userList = new ArrayList<>();
        userList.add(new User("3","带头大哥","36","杭州"));
        userList.add(new User("1","李大锤","23","上海"));
        userList.add(new User("1","李大锤","23","南京"));
        //[User(userid=3, username=带头大哥, age=36, address=杭州), User(userid=1, username=李大锤, age=23, address=上海), User(userid=1, username=李大锤, age=23, address=南京)]
        System.out.println(userList);
        //根据userid去重
        ArrayList<User> collect = userList.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(User::getUserid))), ArrayList::new));
        //[User(userid=1, username=李大锤, age=23, address=上海), User(userid=3, username=带头大哥, age=36, address=杭州)]
        System.out.println(collect);
    }

       过滤

public static void main(String []args){
    //=====================================filte()方法
        List<User> users1 = new ArrayList<>();
        users1.add(User.builder().age(12).userId("D2018").build());
        users1.add(User.builder().age(10).userId("D2020").build());
        users1.add(User.builder().age(10).userId("D2018").build());

        //过滤年龄大于10
        List<User> user2 = users1.stream().filter(v->v.getAge()>10).collect(Collectors.toList());
        System.out.println(user2);
}

       遍历

public static void main(String []args){
        List<String> list = new ArrayList<>();
        list.add("dzx");
        list.add("sxl");
        list.add("sxl1");
        //按照for(int i =0;i<list.size();i++)形式遍历
        ///IntStream.range(0,list.size()),产生[0,list.size())整数序列
        IntStream.range(0,list.size()).forEach(item->{
            System.out.println(list.get(item));
        });
    }

       分组

public static void main(String[] args) {
        //数据准备
        List<User> userList = new ArrayList<>();
        userList.add(User.builder().username("dzx").age("12").userid("1").build());
        userList.add(User.builder().username("sxl").age("12").userid("2").build());
        userList.add(User.builder().username("qwe").age("20").userid("3").build());
        userList.add(User.builder().username("sxl").age("12").userid("3").build());

        //按照用户名分组
        Map<String, List<User>> userMap1 = userList.stream().collect(Collectors.groupingBy(User::getUsername));
        //{dzx=[User(userid=1, username=dzx, age=12)], sxl=[User(userid=2, username=sxl, age=12), User(userid=3, username=sxl, age=12)], qwe=[User(userid=3, username=qwe, age=20)]}
        System.out.println(userMap1);

        //按照用户名_年龄,拼接分组
        Map<String, List<User>> userMap2 = userList.stream().collect(Collectors.groupingBy(item -> item.getUsername() + "_" + item.getAge()));
        //{qwe_20=[User(userid=3, username=qwe, age=20)], sxl_12=[User(userid=2, username=sxl, age=12), User(userid=3, username=sxl, age=12)], dzx_12=[User(userid=1, username=dzx, age=12)]}
        System.out.println(userMap2);

        //按照年龄条件分组
        Map<String, List<User>> userMap3 = userList.stream().collect(Collectors.groupingBy(item -> {
            if ("12".equals(item.getAge())) {
                return "12";
            } else {
                return "20";
            }
        }));
        //{12=[User(userid=1, username=dzx, age=12), User(userid=2, username=sxl, age=12), User(userid=3, username=sxl, age=12)], 20=[User(userid=3, username=qwe, age=20)]}
        System.out.println(userMap3);

        //多级分组,先按照用户名分组,再按照分组后的用户id分组
        Map<String, Map<String, List<User>>> userMap4 = userList.stream().collect(Collectors.groupingBy(User::getUsername, Collectors.groupingBy(User::getUserid)));
        //{dzx={1=[User(userid=1, username=dzx, age=12)]}, sxl={2=[User(userid=2, username=sxl, age=12)], 3=[User(userid=3, username=sxl, age=12)]}, qwe={3=[User(userid=3, username=qwe, age=20)]}}
        System.out.println(userMap4);

        //按照userid分组后,对组内按年龄属性求和,对组内求组员总数
        Map<String, Integer> userMap5 = userList.stream().collect(Collectors.groupingBy(User::getUserid, Collectors.summingInt(item -> Integer.parseInt(item.getAge()))));
        //求和 {1=12, 2=12, 3=32}
        System.out.println(userMap5);
        Map<String, Long> userMap6 = userList.stream().collect(Collectors.groupingBy(User::getUserid, Collectors.counting()));
        //总和 {1=1, 2=1, 3=2}
        System.out.println(userMap6);

        //结合其他收集器:按照姓名分组后,每个分组只需要保留userid信息
        Map<String, List<String>> userMap7 = userList.stream().collect(Collectors.groupingBy(User::getUsername, Collectors.mapping(User::getUserid, Collectors.toList())));
        //{dzx=[1], sxl=[2, 3], qwe=[3]}
        System.out.println(userMap7);
    }

方法引用和构造引用

种类示例说明对应的Lambda表达式
引用类方法类名::类方法函数式接口中被实现方法的全部参数传给该类方法作为参数(a,b…)->类名.类方法(a,b…)
引用特定对象的实例方法特定对象::实例方法函数式接口中被实现方法的参数传给该方法作为参数(a,b…)->特定对象.实例方法(a,b…)
引用某类对象的实例方法类名::实例方法函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数(a,b…)->a.实例方法(b…)
引用构造器类名::new函数式接口中被实现方法的全部参数传给该构造器作为参数(a,b…)->new 类名(a,b…)

引用

  • 《疯狂java讲义第3版》
  • 芋道源码 https://mp.weixin.qq.com/s/vxZthSjG3zNYNFd2oDZK3g
  • Java 8特性 - Collectors toMap https://www.jianshu.com/p/267c53dd4295
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值