新闻资讯

新闻资讯 行业动态

Java中的小知识-----Stream流

编辑:006     时间:2020-03-13
Stream流完全不是I/O流,按照流水线处理方式来考虑代码中的思想;在JDK1.8之后,我们拥有了Lambda表达式,让代码的中心偏向解决实际问题,直达重点。Stream流中大量的使用了Lambda表达式

    Stream流操作思想来自于生产线流水线这种方式,涉及到多步骤操作的情况下,
    这里使用流水线思想进行车工需设计,然后按照设计的模型处理代码中的数据,
    在数据处理的过程中,不浪费资源,没有过多的损耗,每一步操作的内容都是直切主题。
    原材料从头到尾只会占用一份空间,中间过程不会占用空间,最后生成一个结果

Stream流有一些特征:

1.带有很多Stream流操作的方法,filter,limit,map,sorted,skip...这些方法大多是都会使用到函数式接口,有lambda表达式

2.整个Stream流模型操作过程中,只有执行到count,foreach这些方法,操作真正的执行中的模型,如果不存在结果导向,中级的所有操作是无效的,这里得益于Lambda表达式的延后性

3.Stream流是存在一定的管道性,pipelining流水线
操作使用Stream流

    包:
        java.util.stream.Stream<T> JDK1.8新特征
        1.所有的Collection<T>集合都有对应的Stream();
        2.可以通过Stream类中的static Stream of()获取
            static Stream<T> of(T... t);
            static Stream<T> of(T t);

    package com.wcc.b_streamget;
     
    import java.util.*;
    import java.util.stream.Stream;
     
    /**
     * Stream流获取方式
     *      Collection集合
     *      Map双边队列
     *      数组
     * @Author kk
     * @Date 2020/3/12 11:16
     */
    public class Demo1 {
        public static void main(String[] args) {
            //List接口获取对应的Stream类对象
            List<String> list = new ArrayList<>();
            //根据list保存元素的类型来约束对应的Stream类型操作所需类型
            Stream<String> stream = list.stream();
     
            //通过set集合获取对应的Stream流对象
            HashSet<String> set1 = new HashSet<>();
            Stream<String> stream1 = set1.stream();
     
            HashMap<String,String> map = new HashMap<>();
            //map双边队列中所有value对应的collection集合
            Set<String> KeySet = map.keySet();
            Stream<String> stream2 = KeySet.stream();
     
            //Map双边队列中所有value对应的Collection集合
            Collection<String> values = map.values();
            Stream<String> stream3 = values.stream();
     
            //map中有一个方法,可以获取所有键值对类型的set集合
            //Entry ==》键值对,是Map接口的一个成员接口
            Set<Map.Entry<String,String >> entrySet = map.entrySet();
            //获取Map键值对集合的Stream流对象
            Stream<Map.Entry<String ,String>> stream4 = entrySet.stream();
     
            //使用不定长参数获取对应的Stream流对象
            Stream<String> stringStream = Stream.of("江坤", "小坤坤", "小江同学");
            
            String[] arr = {"江","坤坤","江坤坤"};
            Stream<String> arrStream = Stream.of(arr);
            
        }
    }

 
Stream流常用方法

延迟方法:

返回值类型依然是Stream接口本身,并没有影响我们操作的真正资源

允许链式操作:filter(XXX).limit(XXX).sorted(XXX)

终结方法:

返回值类型不是Stream接口本身,要么处理数据,要么返回其他类型数据,并且不再支持Stream流对象链式操作。count,foreach

foreach方法:【终结方法】

    void foreach(Consumer<? super T> action);
     
    /*
        终结方法:
            需要一个Consumer接口进行操作处理,消耗一个数据
            Consumer接口是一个【函数式接口】那就可以使用Lambda表达式
            
            
    */

 

filter方法

    Stream<T> filter(Predicate<? super T> filter);
    /*
        filter是过滤方法,需要的参数是Predicate接口,Predicate是一个函数式接口,可以直接使用Lambda表达运行。
        这里返回值类型是Stream类对象,是经过过滤之后的Stream类型,可以进行链式操作
        Predicate接口中需要实现的方法
            boolean test(T t);
    */

map方法

    <R> String<R> map(Function<? super T, ? super R> fun);
    /*
        类型转换操作,得到的是一个类型转换之后数据类型的Stream流对象
        这里需要的参数是Function函数式接口
            R apply(T t);
            T类型的数据转换成R类型
    */

 

count方法【终结方法】

    int count();
    /*
        返回当前Stream流对象中有多少个元素
        类似有Collection接口下的size().String的length();
        【终结方法】
            一旦执行Stream流对象被关闭
    */

limit方法

    Stream<T> limit(long maxSize);
    /*
        对于当前Stream流对象操作的数据进行限制操作,限制个数到maxSize
        例如:
            Stream流中保存的有10个元素,limit 5 ==> 前五个元素
    */

skip方法

    Stream<T> skip(long index);
    /*
        返回值依然是一个Stream流对象,这里跳过当前Stream
    */

concat方法

    static Stream<T> concat(Stream<? extends T>a , Stream<? extends T>b);
    /*
        拼接两个Stream流对象,是一个静态方法,得到新的Stream流对象
    */

原始操作方式和Stream流方式对比

    1.一个String类型的字符串集合,类似:“1 , 中国 , 16"
    2.过滤掉没有5的数据
    3.跳过前三个数据
    4.限制得到前五个数据
    5.两个String类型集合字符串合并
    6.转换成Person类型
    7.展示数据

方法引用

Lambda冗余问题

 

方法引用的一些小要求

    1.明确对象
        对象是调用者,可以是类对象,类名,super,this,构造方法,数组构造方法
    2.明确的执行方法
        该方法只有名字,不需要显式参数
    3.需要处理的数据【联想推导和省略】
    4. :: 方法引用格式

通过类对象来执行方法引用

    1.明确对象 => 类对象
    2.明确执行的方法 =>自定义
    3.处理的数据 => 简单要求为String类型

代码:

    package com.wcc.d_Lambda;
     
    /**
     * @Author kk
     * @Date 2020/3/12 16:18
     */
     
    /**
     * 自定义类
     */
    class ObjectMethodReference{
        //展示字符串
        public void print(String str){
            System.out.println(str.toLowerCase());
        }
    }
     
    /**
     * 函数式接口,目标是明确约束方法;方法类型是
     *      处理String类型参数
     *      没有返回值
     */
    @FunctionalInterface
    interface Printable{
        void print(String str);
    }
    public class Demo2 {
        public static void main(String[] args) {
            /*
                test方法中需要使用一个Printable接口,执行对应的print方法
                这里需要引用ObjectMethodReference类对象对应的print方法,该方法有展示能力
             */
            ObjectMethodReference obj = new ObjectMethodReference();
            /*
                执行的对象:
                    ObjectMethodReference的类对象
                明确执行的方法:
                    print方法
                执行的目标:
                    “ABCED” 可省略,可推导
             */
            test(obj::print);
     
        }
     
        /**
         *
         * @param printable 函数式接口,约束的是方法类型
         */
        public static void test(Printable printable){
            printable.print("ABCDED");
            printable.print("FGHJKL");
        }
    }

通过类名来执行方法引用

    package com.wcc.d_Lambda;
     
    import java.util.ArrayList;
    import java.util.List;
     
    /**
     * @Author kk
     * @Date 2020/3/12 16:39
     */
     
    /**
     * 函数式接口
     */
    @FunctionalInterface
    interface PrintList{
        /**
         * 方法参数为list的集合
         * 没有返回值
         * @param list List集合
         */
        void print(List<?> list);
    }
     
    /**
     *
     */
    class MethodReference{
        /**
         * 该方法符合要求
         * 没有返回值
         * @param list List集合
         */
        public static void showListInfo(List<?> list){
            for (Object o : list) {
                System.out.println(o);
            }
        }
    }
     
    /**
     * 通过类名来执行方法引用
     */
    public class Demo3 {
        public static void main(String[] args) {
            /*
                明确调用对象
                    当前方法是一个静态方法,需要通过类名调用
                明确调用方法
                    showListInfo
                明确的数据
                    ArrayList<String> list = new ArrayList<>();
                    可省略可推导
             */
            testClass(MethodReference::showListInfo);
            
            testClass(list -> {
                for (Object o : list) {
                    System.out.println(o);
                }
            });
        }
        /**
         * 利用了一个函数式接口做欸方法的参数
         * @param printList 函数式接口
         */
        public static void testClass(PrintList printList){
            ArrayList<String> list = new ArrayList<>();
     
            list.add("BMW");
            list.add("Audi");
     
            printList.print(list);
        }
    }

通过super关键字执行方法引用

Father类

    package com.wcc.d_Lambda;
     
    /**
     * @Author kk
     * @Date 2020/3/12 19:07
     */
    public class Father {
        public void sayHello(){
            System.out.println("你好 Java");
        }
    }

函数式接口:

    package com.wcc.d_Lambda;
     
    /**
     * @Author kk
     * @Date 2020/3/12 19:06
     */
    public interface SaySomeThing {
        void say();
    }

Son类

    package com.wcc.d_Lambda;
     
    /**
     * @Author kk
     * @Date 2020/3/12 19:07
     */
    public class Son extends Father{
        public static void main(String[] args) {
            //Lambda表达式
            testSay(() -> System.out.println("你好"));
            new Son().sonMethod();
     
        }
     
        /**
         * 这里的参数是一个函数式接口,这里需要提供一个符合要求的方法
         * @param sst 函数式接口参数
         */
        public static void testSay(SaySomeThing sst){
            sst.say();
        }
        public void sonMethod(){
            /*
                父类中有一个无参数无返回值的sayHello
                满足当前SaySomeThing函数式接口,方法要求:
                执行的对象
                    super关键字,因为该方法在父类内
                执行的方法
                    sayHello
                无需参数
             */
            testSay(super::sayHello);
        }
     
    }

通过this关键字执行方法引用

ORM接口

    package com.wcc.e_this;
     
    /**
     * @Author kk
     * @Date 2020/3/12 19:13
     */
    public interface ORM {
        /**
         * int => String
         * @param i int类型
         * @return String类型
         */
        String toStringType(int i);
    }

ThisDemo类

    package com.wcc.e_this;
     
    /**
     * @Author kk
     * @Date 2020/3/12 19:15
     */
    public class ThisDemo {
        public void test(){
            String s = testThis(i -> i + ":");
            System.out.println(s);
            
            /*
                调用方法的对象
                    this
                执行的方法
                    turn方法
                处理的数据
                    10(可省略,可联想)
             */
            String s1 = testThis(this::turn);
        }
        public String turn(int i){
            return i + ":字符串";
        }
        public static String testThis(ORM orm){
            return orm.toStringType(10);
        }
     
        public static void main(String[] args) {
            new ThisDemo().test();
        }
    }
————————————————
版权声明:本文为CSDN博主「申士_」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42597414/article/details/104812423
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐