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);
    
        }
    }
    
    
  • 相关阅读:
    C语言温习杂记
    C语言变量类型与内存管理
    解析搜狗新闻语料库
    关于clang, scan-build, 和clang test
    Clang checker类总结
    让你的checker出现在clang的checker list中
    Clang安装配置解释
    Operators 操作
    cumulative_distribution累积分布
    SVM
  • 原文地址:https://www.cnblogs.com/train99999/p/10941388.html
Copyright © 2011-2022 走看看