Lambda-函数式接口-Stream流

一、Lambda

组成Lambda三要素:形式参数、箭头、代码块

格式:(形式参数)->{代码块}

1.Lambda表达式练习(抽象方法无参无返回值)

public class HelloWorld {
    public static void main(String[] args) throws IOException {
        //在主方法中调用useEatable方法
        Eatable e = new Eatablelmpl();
        useEatable(e);

        //匿名内部类
        useEatable(new Eatablelmpl() {
            @Override
            public void eat() {
                System.out.println("一天一苹果,医生远离我");
            }
        });

        //Lambda表达式
        useEatable(() -> {
            System.out.println("一天一苹果,医生远离我");
        });
    }

    private static void useEatable(Eatable e) {
        e.eat();
    }
}
public class Eatablelmpl implements Eatable{
    @Override
    public void eat() {
        System.out.println("一天一苹果,医生远离我");
    }
}
public interface Eatable {
    void eat();
}

2.Lambda表达式练习(抽象方法带参无返回值)

        //匿名内部类
        useEatable(new Eatablelmpl() {
            @Override
            public void eat(String s) {
                System.out.println(s);
                System.out.println("医生远离我");
            }
        });

        //Lambda表达式
        useEatable((String s) -> {
            System.out.println(s);
            System.out.println("医生远离我");
        });

3.Lambda表达式练习(抽象方法带参带返回值)

        //匿名内部类
        useEatable(new Eatablelmpl() {
            @Override
            public int add(int x,int y) {
                return x+y;
            }
        });

        //Lambda表达式
        useEatable((int x,int y) -> {
            return x+y;
        });

4.Lambda表达式的省略模式

参数类型可以省略;

但是有多个参数的情况下,不能只省略一个;

如果参数只有一个,那么小括号可以省略;

如果代码块的语句只有一个,可以省略大括号和分号,如果有return,return也要省略

5.Lambda表达式和匿名内部类的区别

所需类型不同:

匿名内部类:可以是接口,可以是抽象类,可以是具体类

Lambda表达式:只能是接口

使用限制不同:

如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类

如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式

实现原理不同:

匿名内部类:编译之后,产生一个单独的.class字节码文件

Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码咋运行的时候动态生成

二、接口组成更新

1.接口组成更新概述

常量:public statin final

抽象方法:public abstract

默认方法:Java8

静态方法:Java8

私有方法:Java9

2.接口中的默认方法

格式:public default 返回值类型 方法名(参数列表){}

注意事项:默认方法不是抽象方法,所以不强制被重写,重写的时候去掉default关键字;public可以省略,default不能省略

public class HelloWorld {
    public static void main(String[] args) throws IOException {
        Eatable e=new Eatablelmpl();
        e.shou1();
        e.shou2();
        e.shou3();
    }
}
public interface Eatable {
    void shou1();
    void show2();
    default void shou3(){
        System.out.println("show3");
    }
}
public class Eatablelmpl implements Eatable{
    @Override
    public void shou1() {
        System.out.println("show1");
    }

    @Override
    public void show2() {
        System.out.println("show2");
    }
}

3.接口中的静态方法

格式:public static 返回值类型 方法名(参数列表){}

注意事项:静态方法只能通过接口名调用,不能通过实现类名或者对象名调用;public可以省略,static不能省略

static void show4(){
        System.out.println("show4");
    }

Eatable.show4();

3.接口中的私有方法

格式1:public 返回值类型 方法名(参数列表){}

格式2:public static 返回值类型 方法名(参数列表){}

注意事项:默认方法可以调用私有的静态方法和非静态方法;静态方法只能调用私有的静态方法

public class HelloWorld {
    public static void main(String[] args) throws IOException {
        Eatable e=new EatableImpl();
        e.show1();
        e.show2();
        Eatable.method1();
        Eatable.method2();
    }
}
public interface Eatable {
    default void show1(){
        System.out.println("show1方法开始执行");
//        System.out.println("初级工程师");
//        System.out.println("中级工程师");
//        System.out.println("高级工程师");
        show();
        System.out.println("show1方法执行结束");
    }
    default void show2(){
        System.out.println("show2方法开始执行");
//        System.out.println("初级工程师");
//        System.out.println("中级工程师");
//        System.out.println("高级工程师");
        show();
        System.out.println("show2方法执行结束");
    }
    static void method1(){
        System.out.println("method1方法开始执行");
//        System.out.println("初级工程师");
//        System.out.println("中级工程师");
//        System.out.println("高级工程师");
        show();
        System.out.println("method1方法执行结束");
    }
    static void method2(){
        System.out.println("method2方法开始执行");
//        System.out.println("初级工程师");
//        System.out.println("中级工程师");
//        System.out.println("高级工程师");
        show();
        System.out.println("method2方法执行结束");
    }
    static void show(){
        System.out.println("初级工程师");
        System.out.println("中级工程师");
        System.out.println("高级工程师");
    }
}

4.方法引用:(::)

        usePrintable(s -> System.out.println(s));
        usePrintable(System.out::println);

方法引用符::该符号为引用运算符,而他所在的表达式被称为方法引用

Lambda表达式支持的方法引用

(1)引用类方法:类名::静态方法

   public static void main(String[] args)  {
        useConverter((String s)->{
            return Integer.parseInt(s);
        });
        
        useConverter(s -> Integer.parseInt(s));
        
        useConverter(Integer::parseInt);
//        Lambda表达式被类方法替代的时候,他的形式参数全部传递给静态方法作为参数
    }

(2)引用对象的实例方法:对象::成员方法

public class HelloWorld {
    public static void main(String[] args)  {
        usePrinter(s -> {
            System.out.println(s.toUpperCase());
        });

        PrintString p=new PrintString();
        usePrinter(p::printUpper);
//        Lambda表达式被实例方法替代的时候,他的形式参数全部传递给静态方法作为参数
    }
    public static void usePrinter(Printer p){
        p.printUpperCase("heeloworld");
    }
}
public interface Printer {
    void printUpperCase(String s);
}
public class PrintString {
    public void printUpper(String s){
        String result = s.toUpperCase();
        System.out.println(result);
    }
}

(3)引用类的实例方法:类名::成员方法

    public static void main(String[] args) {
        useMyString((String s, int x, int y) -> {
            return s.substring(x,y);
        });

        useMyString((s,x,y)->s.substring(x,y));

        useMyString(String::substring);
    }

(3)引用构造器:类名::new

public class HelloWorld {
    public static void main(String[] args) {
        useStudentBuilder((String name,int age)->{
            Student s=new Student(name,age);
            return s;
        });

        useStudentBuilder(((name, age) -> new Student(name,age)));

        useStudentBuilder(Student::new);
    }
    public static void useStudentBuilder(StudentBuilder s){
        Student stu = s.build("谢老板", 32);
        System.out.println(stu.getName()+stu.getAge());
    }
}

三、函数式接口

1.概述

函数式接口:有且仅有一个抽象方法的接口

@Functionallnterface 

放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败

2.函数式接口作为方法的参数 

public class HelloWorld {
    public static void main(String[] args) {
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"线程启动");
            }
        });

        startThread(()-> System.out.println(Thread.currentThread().getName()+"线程启动"));
    }
    public static void startThread(Runnable r){
        new Thread(r).start();
    }
}

3.函数式接口作为方法的返回值

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String> array=new ArrayList<>();
        array.add("bbbb");
        array.add("aa");
        array.add("c");
        array.add("ddd");

//        Collections.sort(array);
//        System.out.println(array);//[aa, bbbb, c, ddd]

        Collections.sort(array,getComparator());
        System.out.println(array);//[c, aa, ddd, bbbb]
    }
    public static Comparator<String> getComparator(){
//        Comparator<String> comp=new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                return s1.length()-s2.length();
//            }
//        };
//        return comp;

//        return new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                return s1.length()-s2.length();
//            }
//        };

//        return (String s1,String s2)->{
//            return s1.length()-s2.length();
//        };

        return (s1,s2)->s1.length()-s2.length();
    }
}

4.Supplier接口

public class HelloWorld {
    public static void main(String[] args) {
        String string = getString(() -> "林青霞");
        System.out.println(string);

        Integer integer = getInteger(() -> 30);
        System.out.println(integer);
    }
    private static String getString(Supplier<String> sup){
        return sup.get();
    }

    private static Integer getInteger(Supplier<Integer> sup){
        return sup.get();
    }
}

Supplier接口练习:获取最大值

public class HelloWorld {
    public static void main(String[] args) {
        int[] arr={19,50,28,37,46};
        int maxValue=getMax(()->{
            int max=arr[0];
            for(int i=0;i<arr.length;i++){
                if(arr[i]>max){
                    max=arr[i];
                }
            }
            return max;
        });
        System.out.println(maxValue);
    }
    private static int getMax(Supplier<Integer> sup){
        return sup.get();
    }
}

5.Consumer接口

Comsumer<T>:包含两个方法

void accept(T t):对给定的参数执行此操作

default Consumer<T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作

Consumer<T>接口也被称为消费性接口,他消费的数据的数据类型由泛型指定

public class HelloWorld {
    public static void main(String[] args) {
        operatorString("林青霞",s -> System.out.println(s));
        operatorString("林青霞",s -> System.out.println(s),s -> System.out.println(new StringBuilder(s).reverse().toString()));

    }
    public static void operatorString(String name, Consumer<String> con1){
        con1.accept(name);
    }
    public static void operatorString(String name, Consumer<String> con1,Consumer<String> con2){
//        con1.accept(name);
//        con2.accept(name);
        con1.andThen(con2).accept(name);
    }
}

Consumer接口练习:按要求打印信息

public class HelloWorld {
    public static void main(String[] args) {
        String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
        operatorString(strArray, (String str) -> {
            String name = str.split(",")[0];
            System.out.print("姓名:" + name+",");
        }, (String str) -> {
            String age = str.split(",")[1];
            System.out.println("年龄:" + age);
        });
    }

    public static void operatorString(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
        for (String str : strArray) {
            con1.andThen(con2).accept(str);
        }
    }
}

7.Predicated接口

public class HelloWorld {
    public static void main(String[] args) {
//        boolean b1 = checkString("hello", s -> s.length() > 8);
//        System.out.println(b1);//false
        boolean b2 = checkString("hello", s -> s.length() > 8);
        System.out.println(b2);//true

        boolean b3 = checkString("hello", s -> s.length() > 8, s -> s.length() < 15);
        System.out.println(b3);//fasle//true
        boolean b4 = checkString("helloworld", s -> s.length() > 8, s -> s.length() < 15);
        System.out.println(b4);//true//true
    }

    public static boolean checkString(String s, Predicate<String> pre) {
//        return pre.test(s);
        return pre.negate().test(s);
    }

    //    同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2) {
//        return pre1.and(pre2).test(s);
        return pre1.or(pre2).test(s);
    }
}

Predicated接口练习:筛选满足条件数据

public class HelloWorld {
    public static void main(String[] args) {
        String[] str = {"林青霞,30", "柳岩,34", "张曼玉,35", "貂蝉,31", "王祖贤,33"};
        ArrayList<String> arrayList = checkString(str, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 33);
        for (String s : arrayList) {
            System.out.println(s);
        }
    }

    public static ArrayList<String> checkString(String[] str, Predicate<String> pre1, Predicate<String> pre2) {
        ArrayList<String> array = new ArrayList<>();
        for (String s : str) {
            if (pre1.and(pre2).test(s)) {
                array.add(s);
            }
        }
        return array;
    }
}

8.Function接口

public class HelloWorld {
    public static void main(String[] args) {
        convert("100", s -> Integer.parseInt(s));//100

        convert(100, i -> String.valueOf(i + 566));//666

        convert("100", s -> Integer.parseInt(s), i -> String.valueOf(i + 566));//666
    }

    //    定义一个方法,把字符串转换int类型,在控制台输出
    public static void convert(String s, Function<String, Integer> fun) {
        int i = fun.apply(s);
        System.out.println(i);
    }

    //    定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
    public static void convert(Integer i, Function<Integer, String> fun) {
        String s = fun.apply(i);
        System.out.println(s);
    }

    //    定义一个方法,把一个字符串转换为int类型,把int类型的数据加上一个整数之后,转为字符串在控制台输出
    public static void convert(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
//        int i = fun1.apply(s);
//        String str = fun2.apply(i);
//        System.out.println(str);
        String s1 = fun1.andThen(fun2).apply(s);
        System.out.println(s1);
    }
}

Function接口练习:按照指定要求操作数据

public class HelloWorld {
    public static void main(String[] args) {
        String s="林青霞,30";
        convert(s,age->Integer.parseInt(age)+70);
    }
    public static void convert(String s, Function<String, Integer> fun) {
        Integer age = fun.apply(s.split(",")[1]);
        System.out.println(age);
    }
}

四、Stream流

1.Stream流的常见生成方式

public class HelloWorld {
    public static void main(String[] args) {
//        Collection体系的集合可以使用默认方法Stream生成流
        List<String> list = new ArrayList<>();
        Stream<String> listStream = list.stream();

        Set<String> set = new HashSet<>();
        Stream<String> setStream = set.stream();
        
//        map体系的集合间接生成流
        Map<String, Integer> map = new HashMap<>();
        Stream<String> keyStream = map.keySet().stream();
        Stream<Integer> valueStream = map.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

//        数组可以通过Stream接口的静态方法of(T....values)生成流
        String[] strArray = {"hello", "world", "java"};
        Stream<String> strArray1 = Stream.of(strArray);
        Stream<String> strArray2 = Stream.of("hello", "world", "java");
        Stream<Integer> intStream = Stream.of(10, 20, 30);
    }
}

2.Stream流的中间操作之filter

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String > list=new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

//        把list集合中以张开头的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);

//        把list集合中长度为3的元素在控制台输出
        list.stream().filter(s -> s.length()==3).forEach(System.out::println);

//        把list集合中以张开头长度为3的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(System.out::println);
    }
}

3.Stream流的中间操作之limit&&skip

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String > list=new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

//        取前三个数据在控制台输出
        list.stream().limit(3).forEach(System.out::println);//林青霞,张曼玉,王祖贤

//        跳过三个数据,剩下的数据在控制台输出
        list.stream().skip(3).forEach(System.out::println);//柳岩,张敏,张无忌

//        跳过2个元素,把剩下元素的前两个在控制台输出
        list.stream().skip(2).limit(2).forEach(System.out::println);//王祖贤,柳岩
    }
}

3.Stream流的中间操作之concat&&distinct

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String > list=new ArrayList<>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

//        取前4个数据组成一个流
        Stream<String> s1 = list.stream().limit(4);

//        跳过2个数据组成一个流
        Stream<String> s2 =list.stream().skip(2);

//        合并以上两个流并在控制台输出
        Stream.concat(s1,s2).forEach(System.out::println);

//        要求元素不能重复
        Stream.concat(s1,s2).distinct().forEach(System.out::println);
    }
}

4.Stream流的中间操作之sort

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String > list=new ArrayList<>();
        list.add("linqingxia");
        list.add("zhangmanyu");
        list.add("wangzuxian");
        list.add("liuyan");
        list.add("zhangmin");
        list.add("zhangwuji");

//        按照字母顺序把数据在控制台输出
        list.stream().sorted().forEach(System.out::println);
//        按照字符串长度把数据在控制台输出
        list.stream().sorted((s1,s2)->{
            int num=s1.length()-s2.length();
            int num2=num==0?s1.compareTo(s2):num;
            return num2;
        }).forEach(System.out::println);
    }
}

5.Stream流的中间操作之map&&mapToInt

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");
        list.add("60");

//        将集合中的字符串数据转换为整数之后在控制台输出 map:返回由给定函数应用于此流的元素的结果
        list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);

        list.stream().mapToInt(s -> Integer.parseInt(s)).forEach(System.out::println);

//        int sum()返回此流中元素的总和
        int sum = list.stream().mapToInt(s -> Integer.parseInt(s)).sum();
        System.out.println(sum);
    }
}

6.综合练习

public class HelloWorld {
    public static void main(String[] args) {
        ArrayList<String> manlist = new ArrayList<>();
        manlist.add("周润发");
        manlist.add("成龙");
        manlist.add("刘德华");
        manlist.add("吴京");
        manlist.add("周星驰");
        manlist.add("李连杰");

        ArrayList<String> womanlist=new ArrayList<>();
        womanlist.add("林心如");
        womanlist.add("张曼玉");
        womanlist.add("林青霞");
        womanlist.add("柳岩");
        womanlist.add("林志玲");
        womanlist.add("王祖贤");

        Stream<String> s1 = manlist.stream().filter(s -> s.length()==3).limit(3);
        Stream<String> s2 = womanlist.stream().filter(s -> s.startsWith("林")).skip(1);
        Stream<String> s3 = Stream.concat(s1, s2);
        s3.map(Actor::new).forEach(p-> System.out.println(p.getName()));
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值