美文网首页java基础
java基础-day23-函数式接口和Stream流

java基础-day23-函数式接口和Stream流

作者: 触手不可及 | 来源:发表于2021-06-28 09:53 被阅读0次

    函数式接口和Stream

    1. 函数式接口

    1.1 函数式接口概述
    利用接口操作语法格式,对于方法的声明作出二次封装!!!
        方法声明:
            权限修饰符 是否静态 返回值类型 方法名(形式参数列表);
        对于接口而言
            返回值类型 方法名(形式参数列表);
        在使用lambda表达式的过程中
            方法名有个锤子用啊???
            ·关注内容就是返回值,一个形式参数列表
    
    1.2 常用函数式接口
    1. 消费式接口
        方法是消耗一个参数,但是没有返回值
        interface Consumer<T> {
            void accept(T t);
        }
    
    2. 生产者接口
        方法不需要参数,但是存在返回值数据
        Interface Supplier<T> {
            T get();
        }
    
    3. 转换数据类型接口
        指定参数类型,指定返回值类型,将参数转换成对应指定数据类型
        Interface Function<T,R>  {
            R apply(T t);
        }
    
    4. 判断接口
        判断接口,指定数据类型通过当前test方法判断,满足要求返回true,不满足返回false 类似于filter
        Interface Predicate<T> {
            boolean test(T t);
        }
    
    5. 比较器接口
        比较器接口
        interface Comparator<T> {
            int compare(T o1, T o2);
        }
        
        以上所有接口都有对应的@FuntionalInterface 注解约束,当前接口中有且只允许存在一个未完成方法(abstract方法).
    
    1.3 比较器函数式接口
    回顾一个知识点:
        你还记得Arrays? sort方法?
        Arrays.sort(T[] t, Comparator<T> com);
    
    package com.qfedu.a_funtion;
    
    import java.util.Arrays;
    import java.util.Comparator;
    
    public class Demo1 {
        public static void main(String[] args) {
            SinglePerson sp1 = new SinglePerson("老王", 66, '男');
            SinglePerson sp2 = new SinglePerson("老李", 18, '女');
            SinglePerson sp3 = new SinglePerson("老周", 16, '男');
            SinglePerson sp4 = new SinglePerson("张三", 66, '男');
            SinglePerson sp5 = new SinglePerson("李四", 46, '男');
            SinglePerson sp6 = new SinglePerson("王五", 56, '男');
            SinglePerson sp7 = new SinglePerson("赵四儿", 36, '男');
            
            SinglePerson[] arr = {
                sp1, sp2, sp3, sp4, sp5, sp6, sp7   
            };
            
            Arrays.sort(arr, new Comparator<SinglePerson>() {
                @Override
                public int compare(SinglePerson o1, SinglePerson o2) {
                    return o2.getAge() - o1.getAge();
                }
            });
            
            
            Arrays.sort(arr, (p1, p2) -> p2.getAge() - p1.getAge());
            
            for (SinglePerson singlePerson : arr) {
                System.out.println(singlePerson);
            }
        }
    }
    
    1.4 消费函数式接口 Consumer
    消费式接口
        方法是消耗一个参数,但是没有返回值
        interface Consumer<T> {
            void accept(T t);
        }
    
    package com.qfedu.a_funtion;
    
    import java.util.function.Consumer;
    
    /**
     * 消费函数式接口
     *      Consumer接口是封装了一个无返回值有一个参数的方法。
     * @author Anonymous
     *
     */
    public class Demo2 {
        public static void main(String[] args) {
            
            String str = "消费接口的调用";
            
            test(str, new Consumer<String>() {
    
                @Override
                public void accept(String t) {
                    System.out.println(t);
                }
            });
            
            test(str, (s) -> {
                System.out.println("字符串长度:" + s.length());
            });
        }
        
        /**
         * 当前方法带有一个消费接口,需要完成一个有参数无返回值方法,当前接口泛型要求String类型
         * 
         * @param str String类型
         * @param c Consumer消费接口
         */
        public static void test(String str, Consumer<String> c) {
            c.accept(str);
        }
    } 
    
    1.5 生产者接口 Supplier
    生产者接口
        方法不需要参数,但是存在返回值数据
        Interface Supplier<T> {
            T get();
        }
    
    package com.qfedu.a_funtion;
    
    /*
    生产者接口
        方法不需要参数,但是存在返回值数据
        Interface Supplier<T> {
            T get();
        }
     */
    
    import java.util.function.Supplier;
    
    public class Demo3 {
        public static void main(String[] args) {
            Integer[] arr = {1, 3, 5, 17, 9, 2, 4, 6, 8, 10};
            
            Integer max = getMax(arr, new Supplier<Integer>() {
    
                @Override
                public Integer get() {
                    int max = arr[0];
                    for (int i = 1; i < arr.length; i++) {
                        if (max < arr[i]) {
                            max = arr[i];
                        }
                    }
                    
                    return max;
                }
            });
            
            Integer max2 = getMax(arr, () -> {
                int max1 = arr[0];
                for (int i = 1; i < arr.length; i++) {
                    if (max1 < arr[i]) {
                        max1 = arr[i];
                    }
                }
                
                return max1;
            });
            
            SinglePerson sp1 = new SinglePerson("老王", 66, '男');
            SinglePerson sp2 = new SinglePerson("老李", 18, '女');
            SinglePerson sp3 = new SinglePerson("老周", 16, '男');
            SinglePerson sp4 = new SinglePerson("张三", 66, '男');
            SinglePerson sp5 = new SinglePerson("李四", 46, '男');
            SinglePerson sp6 = new SinglePerson("王五", 56, '男');
            SinglePerson sp7 = new SinglePerson("赵四儿", 36, '男');
            
            SinglePerson[] spArr = {
                sp1, sp2, sp3, sp4, sp5, sp6, sp7   
            };
            
            SinglePerson max3 = getMax(spArr, () -> {
                SinglePerson sp = spArr[0];
                
                for (int i = 1; i < spArr.length; i++) {
                    if (sp.getAge() < spArr[i].getAge()) {
                        sp = spArr[i];
                    }
                }
                
                return sp;
            });
            
            System.out.println(max3);
        }
        
        /**
         * 找出指定数据类型数组中的最大值
         * 
         * @param <T> 反正占位符
         * @param t 指定数据类型数组
         * @param s 生产者接口
         * @return 对应数据类型的最大值
         */
        public static <T> T getMax(T[] t, Supplier<T> s) {
            return s.get();
        }
    }
    
    1.6 转换数据类型接口 Function
    转换数据类型接口
        指定参数类型,指定返回值类型,将参数转换成对应指定数据类型
        Interface Function<T,R>  {
            R apply(T t);
        }
    
    package com.qfedu.a_funtion;
    
    import java.util.function.Function;
    
    /**
     * 转换接口
     * @author Anonymous
     *
     */
    public class Demo4 {
        public static void main(String[] args) {
            String str = "骚磊,106,男";
            
            SinglePerson person = change(str, new Function<String, SinglePerson>() {
    
                @Override
                public SinglePerson apply(String t) {
                    String[] split = t.split(",");
                
                    String name = split[0];
                    int age = Integer.parseInt(split[1]);
                    char gender = split[2].charAt(0);
                    
                    return new SinglePerson(name, age, gender);
                }
            });
            
            SinglePerson person2 = change(str, (s) -> {
                String[] split = s.split(",");
                
                String name = split[0];
                int age = Integer.parseInt(split[1]);
                char gender = split[2].charAt(0);
                
                return new SinglePerson(name, age, gender);
            });
            
            System.out.println(person2);
        }
        
        /**
         * 讲字符串内容转换成SinglePerson类型
         * 
         * @param str 数据字符串
         * @param fun 转换接口
         * @return SinglePerson类型
         */
        public static SinglePerson change(String str, Function<String, SinglePerson> fun) {
            return fun.apply(str);
        }
    }
    
    1.7 判断接口 Predicate
    判断接口,指定数据类型通过当前test方法判断,满足要求返回true,不满足返回false 类似于filter
        Interface Predicate<T> {
            boolean test(T t);
        }
    
    package com.qfedu.a_funtion;
    
    import java.security.Permissions;
    import java.util.ArrayList;
    import java.util.function.Predicate;
    
    public class Demo5 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
            
            list.add("手撕大骨头");
            list.add("小鸡炖蘑菇");
            list.add("铁锅炖大鹅");
            list.add("红烧肉");
            list.add("红烧排骨");
            list.add("糖醋里脊");
            list.add("宫保鸡丁");
            list.add("辣子鸡丁");
            list.add("清蒸哈什蚂");
            list.add("西湖牛肉羹");
            list.add("米酒小圆子");
            
            /*
            list.removeIf(new Predicate<String>() {
    
                @Override
                public boolean test(String t) {
                    return t.contains("哈什蚂");
                }
            });
            
            list.removeIf(s -> s.length() > 4);
            */
            list.stream().skip(3).forEach(System.out::println);
        }
    }
    

    2. Stream流式操作

    2.1 先体验后讲解
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    
    /*
     * 1. 要求获取字符串长度大于3的内容
     * 2. 跳过前5个数据
     * 3. 最后保存数据中带有"鸡丁"
     * 4. 展示
     */
    public class Demo2 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
    
            list.add("手撕大骨头");
            list.add("小鸡炖蘑菇");
            list.add("铁锅炖大鹅");
            list.add("红烧肉");
            list.add("红烧排骨");
            list.add("糖醋里脊");
            list.add("宫保鸡丁");
            list.add("辣子鸡丁");
            list.add("清蒸哈什蚂");
            list.add("西湖牛肉羹");
            list.add("米酒小圆子");
            
            // 流水线操作!!!
            list.stream()
                .filter(s -> s.length() > 3)
                .skip(5)
                .filter(s -> s.contains("鸡丁"))
                .forEach(System.out::println);
        }
    }
    
    2.2 Stream流式思想
    流水线!!!
    
    image.png
    2.3 Stream流对象
    Stream流对象
        对于集合提供了一套完备的使用方法,并且提供了获取Stream类对象的方法。
    
    Collection接口中的默认方法。
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    
    常用方法:
        Stream<T> filter(Predicate<? super T> predicate);
            过滤方法,需要的参数是Predicate过滤器接口
                boolean test(T t);
        
        <R> Stream<R> map(Function<? super T, ? extends R> mapper);
            映射方法,将当前Stream流中的T类型数据转换为R类型数据,并且返回的Stream
            类对象对应的是R类型数据
                R apply(T t);
            举例:
                T 土豆
                R 薯片
        
        Stream<T> sorted(Comparator<? super T> comparator);
            排序方法,要求传入的参数是Comparator接口
                int compare(T o1, T o2);
        
        Stream<T> limit(long maxSize);
            限制方法 maxSize最大值,演示看效果
        
        Stream<T> skip(long n);
            跳过方法, n表示跳过的数据个数
        
        void forEach(Consumer<? super T> action);
            forEach 遍历操作使用 需要的接口是Consumer消费者接口
            终止方法!!!返回值类型不是Stream流
            
        long count();
            返回当前Stream类中还剩余多少数据
            终止方法!!!返回值类型不是Stream流
    
    2.4 filter 过滤
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    import java.util.stream.Stream;
    
    /*
     * 过滤
     */
    public class Demo3 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
    
            list.add("冰箱 美的");
            list.add("油烟机 老板");
            list.add("洗衣机 美的");
            list.add("开关面板 西门子");
            list.add("瓷砖 东鹏");
            list.add("卧室门 Tata");
            list.add("锁 德施曼");
    
            /*
             * Stream<String> stream = list.stream(); Stream<String> filter =
             * stream.filter(s -> s.length() > 6); filter.forEach(System.out::println);
             */
            /*
             * Stream流处理过程中,对于原始数据是没有任何印象的,是在操作Stream流缓存数据
             */
            list.stream()
                .filter(s -> s.length() > 6)
                .forEach(System.out::println);
    
            System.out.println(list);
        }
    }
    
    2.5 Map映射
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    
    public class Demo4 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
            
            list.add("1,小赵,16");
            list.add("2,小钱,18");
            list.add("3,小孙,66");
            list.add("4,小李,36");
            list.add("5,小周,26");
            list.add("6,小吴,56");
            list.add("7,小郑,6");
            list.add("8,小王,106");
            list.add("9,小冯,16");
            
            list.stream()
                .map(s -> {
                    String[] split = s.split(",");
                    
                    int id = Integer.parseInt(split[0]);
                    String name = split[1];
                    int age = Integer.parseInt(split[2]);
                    
                    return new Person(id, name, age);
                })
                .forEach(System.out::println);
        }
    }
    
    2.6 sorted排序方法
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    
    public class Demo5 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
            
            list.add("1,小赵,16");
            list.add("2,小钱,18");
            list.add("3,小孙,66");
            list.add("4,小李,36");
            list.add("5,小周,26");
            list.add("6,小吴,56");
            list.add("7,小郑,6");
            list.add("8,小王,106");
            list.add("9,小冯,16");
            
            list.stream()
                .map(s -> {
                    String[] split = s.split(",");
                    
                    int id = Integer.parseInt(split[0]);
                    String name = split[1];
                    int age = Integer.parseInt(split[2]);
                    
                    return new Person(id, name, age);
                })
                .sorted((p1, p2) -> p2.getAge() - p1.getAge())
                .forEach(System.out::println);;
                
            list.stream()
                .map(s -> {
                    String[] split = s.split(",");
                    
                    int id = Integer.parseInt(split[0]);
                    String name = split[1];
                    int age = Integer.parseInt(split[2]);
                    
                    return new Person(id, name, age);
                })
                // sorted() 无参数方法需要借助于当前排序数据的自然顺序,或者Comparable接口
                .sorted() 
                .forEach(System.out::println);;
        }
    }
    
    2.7 limit 和 skip
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    
    public class Demo6 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<String>();
            
            list.add("刘亦菲");
            list.add("高圆圆");
            list.add("佟丽娅");
            list.add("王祖贤");
            list.add("玛丽莲梦露");
            list.add("贾玲");
            list.add("拼多多小岳岳");
            
            list.stream()
                /*
                 * limit是限制最大个数,从0开始到maxSize
                 * limit(int maxSize)
                 */
                .limit(5)
                .forEach(System.out::println);
            
            System.out.println();
            
            list.stream()
                /*
                 * skip是跳过指定数据
                 * skip(3) 是跳过前三个
                 */
                .skip(3)
                .forEach(System.out::println);
        }   
    }
    
    2.8 foreach 和 count
    终止方法!!!
        stream流运行到foreach和count终止Stream流
    
    forEach(System.out::println);
        System.out::println 方法引用
        这里需要【引入,使用】这个方法
    
    package com.qfedu.b_stream;
    
    import java.util.ArrayList;
    
    public class Demo7 {
        public static void main(String[] args) {
            
            ArrayList<String> list = new ArrayList<String>();
            
            list.add("胡歌");
            list.add("古巨基");
            list.add("彭于晏");
            list.add("金城武");
            list.add("成龙");
            list.add("张译");
            list.add("张涵予");
            list.add("吴京");
            list.add("陈道明");
            
            long count = list.stream().count();
            System.out.println(count);
            
            // Lambda表达式
            list.stream().forEach(s -> System.out.println(s));
            
            // 方法引用
            /*
             * System.out::println 
             * System.out 的 println方法
             */
            list.stream().forEach(System.out::println);
            
            /*
             * Demo7::printElement 
             * Demo7的 printElement方法
             */
            list.stream().forEach(Demo7::printElement);
        }
        
        /**
         * 有参数无返回值的方法,需要的参数类型是String类型
         * 
         * @param s String类型
         */
        public static void printElement(String s) {
            System.out.println(s);
        }
    }
    

    相关文章

      网友评论

        本文标题:java基础-day23-函数式接口和Stream流

        本文链接:https://www.haomeiwen.com/subject/czfqultx.html