Java基础_Lambda表达式 函数是接口 Stream流

本文介绍了Java 1.8引入的Lambda表达式,作为函数式编程的基础,以及函数式接口的使用,涵盖了Comparator、Supplier、Consumer、Predicate和Function接口的应用实例。同时展示了Stream流的概念和操作,如过滤、映射和计数。

一、Lambda表达式(1.8特性)

函数式编程始终编程方式,它将电脑视为函数的计算。将业务逻辑细化、抽象、封装成一个个功能函数(方法),并借助语言自带的高阶函数,将整个业务流程转化为函数之间的相互调用,这就是函数是编程。Lambda表达式是接口的匿名内部类替代品,但必须只有一个抽象方法要实现(匿名内部类目的也是对抽象方法的实现)。

函数式接口:符合定义Lambda表达式的接口 

Lambda语法格式  三部分

  1. 参数           【抽象方法的参数列表,与常规方法一致 无参数留空,多个参数用逗号分隔】
  2. ->               【新引入的语法格式 】
  3. 代码体       【方法实现的代码块 逻辑实现体 】

标准格式:(参数类型 参数名称)->{ 代码体 }

【代码】比较器 (数组排序、HashSet、TreeSet 构造时需要构造器)

参数列表的省略原则:参数类型可省略;参数为一个时候 (a) ->{} 可省略为 a ->{} ;无参数时 不能省 ()->{}

方法体的省略原则:大括号内只有一条执行语句,{} ; return  3个一省全省。 ()->{return a-b;}  省略后。()-> a-b

 如: (Person o1, Person o2) -> { return o2.age - o1.age;}// 简化后(o1, o2) -> o2.age - o1.age

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;

public class DemoLambda {
    // Lambda       1.8 JDK 新特性     函数编程 高阶调用低阶函数
    // Stream       1.8 JDK 新特性
    /*前提:是接口匿名内部类替代品、必须只有一个抽象方法实现,这种符合Lambda表达式接口 称之为 函数式接口
    格式:( 参数类型, 参数名称 )-> { 代码语句 }*/
    public static void main(String[] args) {

        // 比较器 (数组排序、HashSet、TreeSet 构造时需要构造器)
        Person[] pers = new Person[3];
        pers[0] = new Person("张三", 12);
        pers[1] = new Person("李四", 9);
        pers[2] = new Person("王五", 15);

        Arrays.sort(pers, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.age - o2.age;
            }
        });
        for (Person per : pers) {
            System.out.println("per = " + per);
        }
        // 比较器简化后 (标准格式)  (参数列表)-> { 代码体 }
        Arrays.sort(pers, (Person o1, Person o2) -> {
                    return o2.age - o1.age;
                }
        );
        //比较器简化后 (省略格式)
        Arrays.sort(pers, (o1, o2) -> o2.age - o1.age);

        for (Person per : pers) {
            System.out.println("per = " + per);
        }
    }
}

class Person {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}

 

二、函数式接口

1、函数式接口的特点

@FunctionalInterface  // 注解 语法限定 对函数式接口的限定,只能有一个需要实现的抽象方法
interface Calculator{  //自定义接口
    int calculate(int a ,int b); // 抽象方法的定义
    // 可以有其他的静态、默认方法
}

【代码】自定义函数式接口

public class DemoFuncInterface {
    public static void main(String[] args) {

        // 1 重写接口方法体、获取接口对象
        Calculator c1 = (a,b)->a+b;
        // 2 函数调用
        int res1 = c1.calculate(100, 200);
        // 3 展示结果
        System.out.println("res1 = " + res1);

        // 明确输入与输出  (自定义函数规则)
        Calculator c2 = (a,b)->a*b;
        int res2 = c2.calculate(19, 6);
        System.out.println("res2 = " + res2);
    }
}
// 注解 对函数式接口的限定,只能有一个需要实现的抽象方法
@FunctionalInterface
interface Calculator{
    int calculate(int a ,int b);
}

2、Supplier <JDK提供>

java.util.function.Supplier<T> 是一个供给型接口、接口中包含一个T get() 方法,用来获取一个范型参数指定类型的数据对象(应用场景:数据提供)

【代码】获取 【1-100】的随机数

import java.util.Random;
import java.util.function.Supplier;// JDK自有 供给型接口

/*Supplier 接口是一个供给型接口 可以用来提供执行类型的数据 获取逻辑具体在get()中实现*/
public class DemoSupplier {
    public static void main(String[] args) {

        // JDK自有 供给型接口 【赘余版】
        Supplier<Integer> demo = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(10);
            }
        };

        // 【简化版】  案例:获取 【1-100】的随机数
        Supplier<Integer> sup = () -> {
            // (重要) 提供标准格式内容
            Random r = new Random();
            int num = r.nextInt(100) + 1;
            return num;
        };
        for (int i = 0; i < 10; i++) {
            Integer res = sup.get();
            System.out.println("res" + i + " = " + res);
        }
        // 简化
        Supplier<Integer> supSim = () -> new Random().nextInt(100) + 1;
        for (int i = 0; i < 10; i++) {
            Integer res = sup.get();
            System.out.println("Sim res" + i + " = " + res);
        }
    }
}

3、Consumer <JDK提供>

java.util.function.Consumer<T> 接口是一个消费型接口,实现抽象方法 void accept(T t)  对传入的数据t进行处理【应用场景:对数据的标准化处理】

【代码】字符串列表按照指定格式输出

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;

/*Consumer 一个消费型接口 实现accept(T t) 对传入的数据t进行逻辑加工处理*/
public class DemoConsumer {
    public static void main(String[] args) {
        // 创建list对象
        ArrayList<String> list = new ArrayList<>();
        boolean bo = Collections.addAll(list, "肖生克的救赎", "罗马假日", "School", "五福临门");
        System.out.println("bo = " + bo); // 全部添加成功
        // 按照规定格式处理 ()
        ArrayList<String> result = new ArrayList<>();
        // 【赘余版】
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("赘余 s = " + s);
            }
        });
        // 【简化版】
        list.forEach((s) -> {
            //(重要) 此处可对接收的对象进行加工处理
            System.out.println("《" + s + "》");
            result.add("《" + s + "》");
        });
        System.out.println("result = " + result);//result = [《肖生克的救赎》, 《罗马假日》, 《School》, 《五福临门》]
        /*
        目前list集合遍历的方式:
        1 普通for循环;2 增强for;3 迭代器Iterator; 4 list.forEach()
         */
    }
}

3、Predicate <JDK提供>

java.util.function.Predicate<T> 接口可以实现对某种类型的数据进行判断,实现抽象方法 boolean test(T t)  对传入的数据逻辑判定【应用场景:数据合法性判断】

【代码】对数字进行奇偶判断 并添加至对应列表

import java.util.ArrayList;
import java.util.Random;
import java.util.function.Predicate;

/*Predicate 实现对某种类型的判断、返回boolean  具体逻辑由test(T t)进行判断实现 */
public class DemoPredicate {
    static ArrayList<Integer> odd = new ArrayList<>(); // 奇数
    static ArrayList<Integer> even = new ArrayList<>();// 偶数

    public static void main(String[] args) {
        // 随机生成10个数据,按照奇偶添加到不同的列表
        Random random = new Random();
        int[] arr = new int[10];
        for (int i = 0; i < 10; i++) {
            arr[i] = random.nextInt(100);
        }
        // 【赘余版】 predicate 偶数-> true
        for (int i : arr) {
            analyze(i, new Predicate<Integer>() {
                @Override
                public boolean test(Integer integer) {
                    return integer % 2 == 0;
                }
            });
        }
        // 【简化版】
        for (int i : arr) {
            analyze(i, x -> x % 2 == 0);
        }
        // 查看结构
        System.out.println("偶数 even = " + even);
        System.out.println("奇数  odd = " + odd);
    }
    public static void analyze(int num, Predicate<Integer> predicate) {
        if (predicate.test(num)) {
            even.add(num);
        } else {
            odd.add(num);
        }
    }
}

5、Function<JDK提供>

java.util.function.Function<T, R> 接口可以实现将一种数据类型T转变为另一种数据类型R,实现抽象方法 R apply(T t)  将传入的数据类型T 转为R 【应用场景:数据类型转变】

【代码】字符串装变为指定类对象

import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;

/*魔法师   将一种类型T转变成另外一种类型R的结构 具体由R apply(T t)方法实现
java.util.function.Function<T, R>{  // T->R
            R apply(T t);
} */
public class DemoFunction {
    public static void main(String[] args) {
        // 案例 将字符串转变成对象
        // 准备字符串
        ArrayList<String> list = new ArrayList<>();
        boolean b = Collections.addAll(list, "小红:18", "小明:17", "大黄:19");
        System.out.println("字符串添加情况 : " + b);
        // 【赘余版】
        for (String p : list) {
            map(p, new Function<String, Person>() {
                @Override
                public Person apply(String s) {
                    String[] splits = s.split(":");
                    Person person = new Person(splits[0], Integer.parseInt(splits[1]));
                    return person;
                }
            });
        }// end for
        // 【简化版】
        for (String p : list) {
            map(p,(s -> {
                String[] splits = s.split(":");
                return new Person(splits[0],Integer.parseInt(splits[1]));
            }));
        }// end for
    }// end main

    public static void map(String str, Function<String, Person> function) {
        // 调用接口实例函数
        Person person = function.apply(str);
        System.out.println("person = " + person);
    }
}

三、Stream流

得益于Lambda所带来的函数式编程,引入全新的Stream概念(写出优雅的代码)

Stream常用方法
方法名方法作用 方法种类是否支持链式调用
count统计个数long cout();终结
forEach逐一处理void forEach(Consumer <? super T> action);终结
filter过滤Stream<T> filter(Predicate <? super T> predicate) ;函数拼接
limit取用前几个Stream<T> limit(long maxSize);函数拼接
skip跳过前几个Stream<T> skip(long n) ;函数拼接
map映射<R> Stream map( Function<? super T, ?extends R> mapper );函数拼接
concat组合static <T>Stream concat( Stream<? extends a, ?extends T> b );函数拼接
import java.util.ArrayList;
import java.util.Collections;

public class DemoStream {
    public static void main(String[] args) {
        // 所有的Collection集合 都默认 stream() 方法获取流
        ArrayList<String> list = new ArrayList<>();
        boolean boo = Collections.addAll(list, "张三", "张三丰", "王二小", "李铁牛", "黄继光");
        System.out.println("boo = " + boo);// 添加成功否

        // 姓张 两个子的有几个人
        long num = list.stream()
                .filter(s -> s.startsWith("张"))
                .filter(s -> s.length() == 2)
                .count();
    }
}

 

收集Stream结果

对流操作完之后,如果需要将其结果保存至集合、数组等

【代码】收集至 List Set Array

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class DemoCollectors {
    public static void main(String[] args) {
        // 成为list
        Stream<String> s1 = Stream.of("A", "B", "C", "D");
        List<String> list = s1.collect(Collectors.toList());
        System.out.println("list = " + list);
        // 成为set
        Stream<String> s2 = Stream.of("A", "B", "C", "D");
        Set<String> set = s2.collect(Collectors.toSet());
        System.out.println("set = " + set);
        // 成为Array
        Stream<String> s3 = Stream.of("A", "B", "C", "D");
        Object[] objects = s3.toArray();
    }
}

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值