zoukankan      html  css  js  c++  java
  • 笔记-迎难而上之Java基础进阶8

    函数式接口

    函数式接口:有且只有一个抽象方法的接口,(可以包含其他默认,静态,私有方法)

    //函数式接口的使用,创建一个函数式接口
    public interface FunctionalInterfaceDemo{
    	public abstract void method();
    }
    
    //实现函数式接口
    public class FunctionalInterfaceDemoImpl implements FunctionalInterfaceDemo{
    	public void method(){
    		System.out.println("我实现了函数式接口");
    	}
    }
    
    public class Test{
    	public static void main(String[] args){
    	//参数是接口,使用接口的实现类对象来调用method方法
    		show(new FunctionalInterfaceDemoImpl());
    	//参数是接口,使用接口的匿名内部类来调用方法	
    		show(new FunctionalInterfaceDemo() {
    			public void method() {
    				System.out.println("我使用了接口的匿名内部类");
    			}
    		});
    	//函数式接口,可以使用Lambda表达式
    	//(参数的内容)->{方法体}
    	show(()->{
    		System.out.println("使用lambda表达式");
    	});
    	}
    	
    	public static void show(FunctionalInterfaceDemo fid){
    		fid.method();
    	}
    }
    //我实现了函数式接口
    //我使用了接口的匿名内部类
    //使用lambda表达式
    

    性能浪费的日志案例

    public class LoggerDemo{
    	public static void main(String[] args){
    		String msg1 = "Hello";
    		String msg2 = "World";
    		String msg3 = "Java";
    		
    		showLog(1,msg1+msg2+msg3);
    	}
    	
    	public static void showLog(int level,String message){
    		//这里如果输入的不是1,那么前面的字符串就会白拼接了
    		//造成了性能浪费
    		if(level==1){
    			System.out.println(message);
    		}
    	}
    }
    

    使用Lambda优化日志

    //Lambda特点,延迟加载
    public class LambdaDemo2{
    	public static void main(String[] args){
    		String msg1 = "Hello";
    		String msg2 = "World";
    		String msg3 = "Java";
    		//方法参数是一个接口,可以传递接口的匿名内部类
    		showLog(1,new MessageBuilder(){
    			public String builderMessage(){
    				return msg1+msg2+msg3;
    			}
    		});
    		
    		//调用方法,接口参数是函数式接口,可以使用的是Lambda表达式
    		showLog(1,()->{
    			return msg1+msg2+msg3;
    		});
    		//感觉使用匿名内部类作为参数比较好理解,但是使用Lambda表达式的话比较简洁,但是也不好理解,有点抽象
    	}
    	
    	public static void showLog(int level,MessageBuilder mb){
    		//如果日记等级是1,就调用MessageBuilder的方法
    		if(level == 1){
    			//不等于1的话,这一段就不会执行,就不会调用到方法,就不会拼接字符串,就不会存在性能浪费
    			System.out.println(mb.builderMessage());
    		}
    	}
    }
    

    函数式接口作为方法的参数案列

    public class RunnableDemo{
    	public static void main(String[] args){
    		//调用startThread方法
    		//方法参数是一个函数式接口,可以使用Lambda表达式
    		//当然也可以通过接口的实现类对象,或者匿名内部类对象进行传参
    		//首先使用匿名内部类对象来调用方法
    		startThread(new Runnable(){
    			public void run(){
    				System.out.println(Thread.currentThread().getName()+"-->线程启动");
    			}
    		});
    		//使用Lambda表达式作为参数
    		startThread(()->{
    			System.out.println(Thread.currentThread().getName()+"-->线程启动");
    		});
    		
    	}
    	//接口Runnable是一个函数式接口
    	public static void startThread(Runnable run){
    		//调用我startThread方法,我就开启一条线程
    		//Thread类的有一个带Runnable接口的构造方法,
    		//传递该接口,就可以开启一条线程对象
    		new Thread(run).start();
    	}
    	//大概能理解,但是有点绕
    }
    
    函数式接口作为返回值得类型
    import java.util.*;
    public class ComparatorDemo{
    	public static void main(String[] args){
    		String[] arr ={"aaa","b","ccccc","dddddddd"};
    		//把数组的内容以字符串的形式打印出来
    		System.out.println(Arrays.toString(arr));
    		//根据比较器产生的顺序对指定对象组进行排序
    		Arrays.sort(arr,getComparator());
    		System.out.println(Arrays.toString(arr));
    	}
    	
    	//定义一个方法,其返回值类型是Comparator
    	public static Comparator<String> getComparator(){
    		return (o1,o2)->o2.length()-o1.length();
    	}
    }
    
    常用的函数式接口_Supplier接口
    import java.util.function.*;
    /*
    * Supplier<T> 接口被称之为生产性接口,接口指定的类型是什么,接口中get方法就会返回一个相同的类型
    */
    public class SupplierDemo {
        public static void main(String[] args) {
    		//匿名内部类
            System.out.println(getString(new Supplier<String>() {
                @Override
                public String get() {
                //下面的方法getString执行方法体的语句,sp.get(),获取到了"春风扶槛露华浓",传递给main方法,main方法打印输出
                    return "春风扶槛露华浓";
                }
            }));
            //按照我的理解这里的return 把"云想衣裳花想容"传递给了下面的方法getString,下面的方法再次return回来,所以就打印输出"云想衣裳花想容"
            //
            String s = getString(()->{
                return "云想衣裳花想容";
            });
            System.out.println(s);
        }
        //Supplier是一个函数式接口
        public static String getString(Supplier<String> sp){
            return sp.get();
        }
    }
    //看视频不是很理解,但是写的话自己理清楚思路按照Lambda的格式,一步一步想清楚,勉强能写出来,
    
    //求最大值
    import java.util.function.*;
    
    public class MaxDemo {
        public static void main(String[] args) {
            int[] arr= {12,42,33,55,23,75,24};
            //调用getMax方法
            //参数是一个函数式接口,可以使用Lambda表达式
            int maxNum=getMax(()->{
                int max=arr[0];
                for(int i:arr){
                    if(i>max){
                        max=i;
                    }
                }
                //要求有返回,必须加return
                return max;
            });
            System.out.println(maxNum);
        }
    
        public static int getMax(Supplier<Integer> sp){
            //调用Supplier的get方法,他会返回指定的类型
            return sp.get();
        }
    
    }
    
    
    Consumer接口
    import java.util.function.*;
    
    public class ConsumerDemo {
        public static void main(String[] args) {
            //调用method,函数式接口的accept有参数
            method("李白",(String name)->{
                //方法体写要对name做什么操作
                System.out.println("云想衣裳花想容->"+name);
            });
        }
        //Consumer<T>接口是一个消费的数据
        //泛型指定什么类型,就可以使用方法accept方法消费什么类型的数据
        public static void method(String name,Consumer<String> con){
            //当你调用method的时候,你可以对name进行指定的操作
            con.accept(name);
        }
    }
    
    

    ​ 个人总结Lambda表达式的几个知识点

    有return语句的方法,L表达式也要跟着return,不然编译不通过,我想不通为什么,反正就是要这样

    L表达式要不要加参数,好像是看函数式接口的抽象方法有没有参数

    要执行的操作都是在L表达式中的方法体给出

    Consumer接口默认方法andThen

    andThen:需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费

    package demo18;
    
    import java.util.function.Consumer;
    
    public class ConsumerDemo1 {
        public static void main(String[] args) {
            //调用方法
            method("李白",
                    //可以指定参数类型
                    (String name)->{
                        System.out.println("云想衣裳花想容");
                    },
                    //也可以不指定参数类型
                    (name)->{
                        System.out.println("春风扶槛露华浓"+name);
                    });
        }
        public static void method(String name, Consumer<String> con1,Consumer<String> con2){
                //默认方法andThen方法可以把两个接口连接在一起,一起消费数据name,
                //消费的方式可以在Lambda表达式中给出
            con1.andThen(con2).accept(name);
        }
    }
    
    
    Consumer接口练习
    package demo18;
    
    import java.util.function.*;
    
    public class Test {
        public static void main(String[] args) {
                //准备一个数组
                String[] arr={"孙策,大乔","周瑜,小乔","吕布,貂蝉"};
                //调用方法method
                method(arr,(s)->{
                    //遍历获得元素,传递到了这里,
                    //现在对元素进行切割,切割返回的是一个素组,通过索引0来获取需要的元素
                   String name= s.split(",")[0];
                   System.out.print("男: "+name);
                        },
                    //遍历获得元素,现在轮到我来对他进行切割,需要1元素    
                        (s)->{
                    String name1= s.split(",")[1];
                    System.out.println(" 女 "+name1);
                        });
        }
        public static void method(String[] str, Consumer<String> con1,Consumer<String> con2){
            //只要调用我,我就把他传递过来的集合给遍历了,获取出每一个元素,让con1和con2一起去操作这个元素
            //具体的操作步骤已经在Lambda表达式中给出
            for(String s :str){
                con1.andThen(con2).accept(s);
            }
    
        }
    }
    
    
    Prediat接口
    package demo18;
    
    import java.util.function.*;
    
    public class PredicateDemo {
        public static void main(String[] args) {
            //调用方法method
            //这个函数式接口Predicate是有参数的
            //等一下不要忘记把变量名改一下
            boolean b= method("云想衣裳花想容",(String s)->{
                return s.equals("春风扶槛露华浓");
    
            });
            System.out.println(b);
        }
        public static boolean method(String s,Predicate<String> pre){
            //调用Predicate中的方法test,对传递进来的参数进行判断
            //具体的判断步骤可以在Lambda表达式中写出
            return pre.test(s);
        }
    }
    
    
    Predicate接口_默认方法and
    package demo18;
    
    import java.io.InputStream;
    import java.util.function.Predicate;
    
    public class PredicateDemo1 {
        public static void main(String[] args) {
           boolean b =  method("云想衣裳花想容",(String str)->{
                    System.out.println(str.length());
                    return str.length()>5;
                    },
                    (String str)->{
                            return str.contains("花");
                    });
           System.out.println(b);
        }
        public static boolean method(String str, Predicate<String> pre1 , Predicate<String> pre2){
            //对传递过来的str进行判断
            //and,两个为true 就返回true
           return pre1.and(pre2).test(str);
        }
    }
    
    

    Predicate接口_默认方法or和negate

    or有一个为true,就为true

    negate是取反的意思,

    Predicate接口的练习

    img

    import java.util.*;
    import java.util.function.*;
    
    public class Test1 {
        public static void main(String[] args) {
            String[] array = {"迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男", "赵丽颖,女"};
            ArrayList<String> list = method(array,
                    (String s) -> {
                        String name = s.split(",")[0];
                        boolean b1 = name.length() == 4;
                        return b1;
                    }
                    , (String s) -> {
                        String sex = s.split(",")[1];
                        boolean b2 = sex.equals("女");
                        return b2;
                    });
            System.out.println(list);
        }
    
        public static ArrayList<String> method(String[] arr, Predicate<String> pre1, Predicate<String> pre2) {
            //定义一个集合,用来接收条件满足的元素
            ArrayList<String> list = new ArrayList<String>();
            //对传递进来的参数进行判断
            for (String s : arr) {
                //在Lambda表达式中进行具体的操作
                boolean b = pre1.and(pre2).test(s);
                //在Lambda表达式中如果操作完了,就会执行下面这一步
                if (b) {
                    list.add(s);
                }
            }
            return list;
        }
    }
    
    
    Function接口

    Function接口的抽象方法 R apply(T t),根据类型T的参数获取类型T的结果

    import java.util.function.*;
    
    public class FunctionDemo {
        public static void main(String[] args) {
            String s = "1234";
            change(s,(String str)->{
                return Integer.parseInt(str);
    
            });
        }
        public static void change(String s, Function<String,Integer> fun){
            Integer in = fun.apply(s);
            System.out.println(in);
        }
    }
    
    
    import java.util.function.*;
    
    public class FunctionDemo {
        public static void main(String[] args) {
            String s = "123";
            change(s,
                    (String str) -> {
                        return Integer.parseInt(str) + 10;
                    }
                     ,(Integer i) -> {
                        return i + "";
                    });
        }
    
        public static void change(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
            String ss = fun1.andThen(fun2).apply(s);
            System.out.println(ss);
    
        }
    }
    
    
  • 相关阅读:
    739. Daily Temperatures
    556. Next Greater Element III
    1078. Occurrences After Bigram
    1053. Previous Permutation With One Swap
    565. Array Nesting
    1052. Grumpy Bookstore Owner
    1051. Height Checker
    数据库入门及SQL基本语法
    ISCSI的概念
    配置一个IP SAN 存储服务器
  • 原文地址:https://www.cnblogs.com/train99999/p/10941388.html
Copyright © 2011-2022 走看看