>>分享Java编程技术,对《Java面向对象编程》等书籍提供技术支持 书籍支持  卫琴直播  品书摘要  在线测试  资源下载  联系我们
发表一个新主题 开启一个新投票 回复文章 您是本文章第 13343 个阅读者 刷新本主题
 * 贴子主题:  Java函数式接口和Stream流 回复文章 点赞(0)  收藏  
作者:sunshine    发表时间:2021-09-05 01:13:31     消息  查看  搜索  好友  邮件  复制  引用

    

函数式接口和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流式思想
流水线!!!

             点击在新窗口中浏览原图
CTRL+鼠标滚轮放大或缩小

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);
    }
}

----------------------------
原文链接:https://www.jianshu.com/p/acc5bfca6455

程序猿的技术大观园:www.javathinker.net



[这个贴子最后由 flybird 在 2021-09-11 10:34:50 重新编辑]
  Java面向对象编程-->第一个Java程序
  JavaWeb开发-->使用Session(Ⅱ)
  JSP与Hibernate开发-->Java应用分层架构及软件模型
  Java网络编程-->通过JDBC API访问数据库
  精通Spring-->通过Vuex进行状态管理
  Vue3开发-->通过Axios访问服务器
  java实现动态编译并动态加载
  购书咨询
  靠一个HashMap的讲解打动了头条面试官
  Eclipse和MyEclipse的区别
  内部类的种类和用法
  Java并发之volatile关键字内存可见性问题
  volatile 实现原理
  Synchronized与ReentrantLock区别总结
  Eclipse使用指南:快速修复功能
  Java设计模式:状态模式
  Java设计模式:观察者模式
  Java 入门实用代码:汉诺塔算法
  通过Java读取Excel数据
  jdbc连接各种数据库代码
  类加载中的双亲委派模型
  更多...
 IPIP: 已设置保密
楼主      
1页 0条记录 当前第1
发表一个新主题 开启一个新投票 回复文章


中文版权所有: JavaThinker技术网站 Copyright 2016-2026 沪ICP备16029593号-2
荟萃Java程序员智慧的结晶,分享交流Java前沿技术。  联系我们
如有技术文章涉及侵权,请与本站管理员联系。