Java8 特性-stream流①

Java8 特性-stream①

  • 集合与流的区别:

  • 集合好比看电影时下载到本地,然后本地观看;流相当于在线观看;集合是将整部电影都存储到本地,是一个容器内完整的数据;而流是更大更广义,我们只浏览流到本地的数据;
  • 读Stream组成结构:

  • A:数据源;B:中间处理;C:终结方法;
  1. A:数据的起源,Stream流的来源,所有可以转换为Stream流的对象或是容器,如图1-1;
  2. B:Stream流的处理过程,但是不会改变流,如图1-2;
  3. C:将Stream流转换为另一种对象或是容器,如图1-3;
  4. 比如获取一个文件或者读取List,Set等都可以转换为Stream流,均是数据源的部分;filter,map等均属于中间处理过程,处理后流仍是流,对象不会被改变;forEach,collect等均属于终结方法,forEach没有返回值,而collect将原来的流归纳为新的对象;

图 1-1

图1-2

图1-3

  • 创建Stream:

  1. stream() − 为集合创建串行流。

  2. parallelStream() − 为集合创建并行流。

Stream<String> stream = Stream.of( "111", "2222", "333", "44444", null, "777", "2222" );
  • 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);

  • collect方法,可以将 Stream转换为想要的容器,比如Map、Set、List等;

List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","2222" );
Set<String> collect = list.stream().filter( f -> f != null ).filter( (String f) -> !f.equals( "111" ) ).collect( Collectors.toList() ).stream().filter( (String f) -> !f.equals( "777" ) ).collect( Collectors.toSet() );
  • filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;
  • filter过滤函数是可以重复调用的;
  • 案例中过滤掉空值,过滤点String 为111和777的值
List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","2222" );
        Set<String> collect = list.stream().filter( f -> f != null ).filter( (String f) -> !f.equals( "111" ) ).collect( Collectors.toList() ).stream().filter( (String f) -> !f.equals( "777" ) ).collect( Collectors.toSet() );
        collect.forEach( f-> System.out.println(f) );
  • 测试结果

  • map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型;
  • 这里map可以理解为对象处理器,针对当前对象处理;
  • 如果只有一行代码,默认返回该代码结果,省略return语句,多行代码需要在->后加方法体{},并且加return语句;
  • flatMap将对象平行化处理;
  • 一段代码更好的理解 flatMap 与 map 的区别
List<String> list = new ArrayList<>();

        list.add("Holle world and you world");
        list.add("爱 要 坚持 且 持久");

        /**
         * Stream.flatMap ,平由化(把内部元素当作一个原处理)
         * 八个 string对象
         * 针对对象内细微元素
         * 必须返回 Stream 对象
         */
        List<String> result1 = list.stream().flatMap(t -> Stream.of(t.split(" ")))
                .collect(Collectors.toList());
        System.out.println(result1.size());
        result1.forEach(System.out::println);
        System.out.println("------------------------------------------------------------------------------");
        /**
         * 这个例子可以当作stream进行了两次for循环,快速梳理数据
         */
        String[] words1 = new String[]{"Hello","World"};
        String[] words2 = new String[]{"ccd","World"};
        List<String> a = Arrays.stream(words1)
                .flatMap(w1 ->Arrays.stream(words2).filter(w2 -> w1.equals(w2)))
                .distinct()
                .collect(Collectors.toList());
        a.forEach(System.out::println);


        /**
         * Stream.map , 原生态 (原生态处理)
         * 两个 String[],集合内数据结构被改变了
         * 针对对象
         * 返回任意对象
         */
        List<String[]> result2 = list.stream().map(t -> t.split(" "))
                .collect(Collectors.toList());
        System.out.println(result2.size());
        result2.forEach(System.out::println);

        System.out.println("------------------------------------------------------------------------------");
        result2.stream().forEach( array ->{
            System.out.println(array.length);

            for (String s : array) {
                System.out.println(s);
            }
        });

  • mapToInt:
List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","2222" );
        int sum = list.stream().filter( o -> o != null ).mapToInt( (String m) -> Integer.valueOf( m ) ).sum();
        System.out.println(sum);

测试结果:

  • map:
 List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","2222" );
 Set<Double> map = list.stream().filter( f -> f != null ).map( (String m) -> Double.valueOf( m ) ).collect( Collectors.toSet() );
        map.forEach( s-> System.out.println(s) );
  • 测试结果

  • flatMap:
List<String> list = Arrays.asList( "张三", "李四", "王二" );
        List<String> collect = list.stream().flatMap( m -> Stream.of( m.split( "" ) ) ).collect( Collectors.toList() );
        collect.forEach( c-> System.out.println(c) );
  • 测试结果:

  • peek: 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;换言而知,就是对元数据的修改,可以理解为一个没有返回值的方法,只可以对传进来的参数进行处理
/**
     * 在闭包中,所有属性默认是被 'final'修饰的
     * 不能使用‘=’赋值,需要使用反射更改权限
     * 如果是引用数据类型,可以get、add等封装方式直接赋值
     * @param args
     */
    public static void main(String[] args) {
        String[] words1 = new String[]{"Hello","World"};
        List<String> strings = Arrays.stream(words1)
                .peek(s -> {
                    Class<String> stringClass = String.class;
                    try {
                        Field value = stringClass.getDeclaredField("value");
                        value.setAccessible(true);
                        value.set(s,"1".toCharArray());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                })
                .collect(Collectors.toList());
        strings.forEach(System.out::println);
    }
  • limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;
  • skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;
  • 一般skiplimit连用,实现数据分片效果;skip跳过,limit分片数据;
  • 对于distinctcount等聚合函数,可以理解为sql语句执行顺序那样,重要的是每一步要清晰的知道返回数据结果结构,读取这样的代码,貌似在读一篇文章;
List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","sss" );
        List<String> collect = list.stream().filter( f->f!=null ).distinct().skip( 2 ).limit( 3 ).collect( Collectors.toList() );
        collect.forEach( System.out::println );
        long count = list.stream().filter( f -> f != null ).distinct().skip( 2 ).limit( 3 ).count();
        System.out.println("-----------------------------");
        System.out.println(count);

 测试结果:

  • allMatch:是不是Stream中的所有元素都满足给定的匹配条件;
  • anyMatch:Stream中是否部分元素满足匹配条件;
  • findFirst: 返回Stream中的第一个元素,如果Stream为空,返回空Optional;
  • noneMatch:是不是Stream中的所有元素都不满足给定的匹配条件;
  • max和min:使用给定的比较器(Operator),返回Stream中的最大|最小值;
  • Operator是java8针对java.lang.NullPointerException问题提出的问题解决类;
  • isPresent和ifPresent一般跟在比较断言后,提出对结果的猜想;
List<String> list = Arrays.asList( "111", "2222", "333", "44444",null,"777","2222" );
        boolean b1 = list.stream().allMatch( m -> m == null );
        System.out.println("是否全部为空" + b1);
        boolean b2 = list.stream().anyMatch( m -> m == null );
        System.out.println("是否部分为空" + b2);
        boolean b3 = list.stream().noneMatch( m -> m == null );
        System.out.println("是否全部不为空" + b3);
        System.out.println("-----------------------------");
        Optional<String> max = list.stream().filter( f -> f != null ).max( (m1, m2) -> Integer.valueOf( m1 ) - Integer.valueOf( m2 ) );

        System.out.println(max.orElse( null ));
        System.out.println("-----------------------------");

        boolean present = list.stream().filter( f -> f != null ).max( (m1, m2) -> Integer.valueOf( m1 ) - Integer.valueOf( m2 ) ).isPresent();
        System.out.println(present);
        System.out.println("-----------------------------------");

        list.stream().filter( f -> f != null ).max( (m1, m2) -> Integer.valueOf( m1 ) - Integer.valueOf( m2 ) ).ifPresent(s-> System.out.println(s));

测试结果:

  • stream实现分组,返回结果Map,会将分组元素作为Map的Key,相对应的数据为Value
  • 下面的例子是封装一个IPhone对象,对象给有颜色和重量两个属性,然后按颜色属性分组

  • 利用分组实现转换Map
List<IPhone> list = getList();
        Map<String, List<IPhone>> collect = list.stream().collect( Collectors.groupingBy( IPhone::getColor ) );
        System.out.println(collect.toString());
  • 测试结果为:

  • stream转Map,这个需要指定Key和Value
List<IPhone> list = getList();
        Map<String, Integer> collect = list.stream().collect( Collectors.toMap( IPhone::getColor, IPhone::getWeight ) );
        System.out.println(collect.toString());
  • 测试结果

  • Reduce属于归纳性操作,看参数,第一个是U泛型,也就是输入类型的参数,最为初始值,第二个BiFunction,接收T,U参数,返回U类型参数,BinaryOperator接收U,U类型,并返回U类型;
  • 无论是提前拟订好的容器,还是接到的返回值,其值对应的内存地址是一样的,也就是说对象(指针指向)是一样的,如果将提前拟订好的容器进行==或者equals对比其结果为true;
List<String> list = Arrays.asList( "张三", "李四", "王二" );
        
        StringBuffer sb = new StringBuffer();//也可以在下方拟订匿名容器,这样就需要接返回值
        System.out.println("输出初始化StringBuffer:"+sb);
        StringBuffer reduce = list.stream().reduce( sb, (s1, s2) -> s1.append( s2 ), StringBuffer::append );
        System.out.println(sb==reduce);
        System.out.println(sb.equals( reduce ));
        System.out.println(sb);
        System.out.println("----------------------------");
        ArrayList<String> reduceList = list.stream().reduce( new ArrayList<String>(), (a1, a2) -> {
            a1.add( a2 );
            return a1;
        }, (b1, b2) -> {
            b1.addAll( b2 );
            return b1;
        } );
        reduceList.forEach( s-> System.out.println(s) );
        System.out.println("---------------------------------");
        HashMap<Object, Object> reduceMap = list.stream().reduce( new HashMap<>(), (m, m1) -> {
            m.put( m1, m1 );
            return m;
        }, (m, m1) -> {
            m.putAll( m1 );
            return m;
        } );
        System.out.println(reduceMap.toString());
  • 测试结果

方法很多,还需要理解与练习

chenyb 随笔记录,只为方便自己学习

2019-10-012

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值