Java8新特性(一)Lambda表达式

Java8新特性(一)Lambda表达式

  • lambda出现的原因

  • 减少代码量

  • 避免匿名内部类参数之间的混淆

  • 降低内存消耗,使用lambda表达式比使用匿名内部类或者子类的方式更加节省空间,主要原因还是因为java8后jvm结构发生了变化

  • 举个栗子:过滤指定特征的苹果

//苹果实体类
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Apple {
   private String color;
   private long weight;
}

//过滤苹果类
public class FilterApple {
    //需求一:删选出指定颜色的苹果
    public static List<Apple> findGreenApple(List<Apple> apples){
        List<Apple> list = new ArrayList<>();
        for (Apple apple : apples) {
            if("green".equals(apple.getColor())){
                list.add(apple);
            }
        }
        return list;
    }

    //需求二:筛选出颜色为红色的苹果,更改策略,采用条件进行过滤
    public static List findApple(List<Apple> apples,String color){
        List<Apple> list = new ArrayList<>();
        for (Apple apple : apples) {
            if(color.equals(apple.getColor())){
                list.add(apple);
            }
        }
        return list;
    }

    //需求三:根据苹果的各种条件筛选,如颜色和重量,利用策略模式
    public  interface AppleFilter{
        boolean filter(Apple apple);
    }

    public static List<Apple> findApple(List<Apple> apples,AppleFilter appleFilter){
        List<Apple> list = new ArrayList<>();
        for (Apple apple : apples) {
            if(appleFilter.filter(apple)){
                list.add(apple);
            }
        }
        return list;
    }

    //利用各种各样的过滤器去过滤
    public static class GreenAnd150Filter implements AppleFilter {
        @Override
        public boolean filter(Apple apple) {
            return "green".equals(apple.getColor())&&apple.getWeight()>=160;
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        List<Apple> list = Arrays.asList(
				Apple.builder().color("green").weight(150).build(),
				Apple.builder().color("yellow").weight(120).build(),
				Apple.builder().color("green").weight(180).build());
       /** 
       //寻找绿色的苹果
        List<Apple> greenApple = findGreenApple(list);
		assert greenApple.size() == 2 : "不符合预期";  //断言
		for (Apple apple : greenApple) {
			System.out.println(apple);
		}
		**/
        /**
        //传入一个条件
        List<Apple> greenApples = findApple(list,"green");
	    System.out.println(greenApples);
	    **/
        /**
        //传入一个过滤器
        List<Apple> result = findApple(list,new GreenAnd150Filter());
	    System.out.println(result);
        **/
        /**
        //采用匿名内部类的方式
        List<Apple> yellowList = findApple(list, new AppleFilter() {
			@Override
			public boolean filter(Apple apple) {
				return "yellow".equals(apple.getColor());
			}
		});
		System.out.println(yellowList);
        **/
    }
}

//为什么匿名内部类参数容易混淆...
public class AnonymousInnerClass {
	public final int value = 4;
	public void doIt(){
		int value = 6;
		Runnable r = new Runnable() {
			public final int value = 7;
			@Override
			public void run() {
				int value = 8;
				System.out.println(this.value);
			}
		};
		r.run();
	}

	public static void main(String[] args) {
		AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
		anonymousInnerClass.doIt();
	}
}
  • lambda表达式的简单使用

  • 什么情况使用lambda表达式?

    • 接口且接口中只含有一个方法
    • default或静态方法除外
  • 基于lambda表达式对以上栗子进行改进

    • java8中,如果一个接口只有一个方法,可视为一个FunctionInterface,表示它可以使用lambda进行操作。

      List<Apple> lambdaResult = findApple(list, (Apple apple) -> {
      			return apple.getColor().equals("green");
      		});
      
      //上式可以简写,因为只有一个参数,它会推导它是apple类型的,只有一个参数,也可以把括号去掉
      		List<Apple> lambdaResult2 = findApple(list, (apple) -> {
      			return apple.getColor().equals("green");
      		});
      
      //扩展--lambda表达式需要满足的条件:
      			//有且只有一个方法,default和static方法除外,它会在编译的时候判断,可以不标注它为FunctionalInterface,类似的有Runner
      
      
  • lambda表达式语法

  • 语法:以(o1,o2) -> o1.getColor().compareTo(o2.getColor());为例,其中拆解为三部分:参数列表,箭头,lambda体,可泛化为以下格式

    • ((parameters) -> expression
    • (parameters) -> {statments;}
    • ​ ()->{}
  • where、how(如何使用,以及在哪里使用)

    • 什么样的接口是FunctionalInterface?

      • 只有一个抽象的方法,default和static方法除外(1.8新特性)
    • 常见的可使用lambda的方法

      //传入一个参数,判断其是否满足条件或其他
      Predicate boolean test(T t);
      //消费,处理
      Consumer  void accept(T t);
      //传入一个T类型参数,返回一个R类型的,两者可以相同
      Function<T,R> R apply(T t);
      //提供一个参数,只是get一个东西
      Supplier<T> T get();
      
  • 几个简单的lambda栗子

    public class LambdaExpression {
        public interface Test{
                public String fun();
        }
        
        public static void main(String[] args) {
             //1.定义比较器,传入比较器进行比较
    		Comparator<Apple> byColor = new Comparator<Apple>() {
    			@Override
    			public int compare(Apple o1, Apple o2) {
    				return o1.getColor().compareTo(o2.getColor());
    			}
    		};
    		List<Apple> list = Collections.emptyList();
    		list.sort(byColor);
        
        	//引入lambda表达式优化
    		//类型推导,可以不用写return
    		Comparator<Apple> byColor2 = (o1,o2)->o1.getColor().compareTo(o2.getColor());
    		list.sort(byColor2);
    		//可以写return,  =(o1,o2) -> {return o1.getColor().compareTo(o2.getColor());};
    		
    		//2.lambda表达式举例:(String s) -> s.length();返回类型:Function
    		Function<String, Integer> flambda = s -> s.length();
    		System.out.println(flambda.apply("hello")); //5
    		
    		//3.Predicate使用示例:(Apple a) -> a.getColor().equals("green");返回类型:Predicate
    		Predicate<Apple> appleFilter = a -> a.getColor().equals("green");
            
      
        }
    }
    
  • lambda表达式的详细使用

  • 通过栗子了解lambda表达式的使用

    public class LambdaUsage {
        @FunctionalInterface
        public interface Adder{
            int add(int a,int b);
        };
        //@FunctionalInterface,不是,处理有父类的add抽象方法外,还有自己的重载的add方法实现
    	public interface SmartAdder extends Adder{
    		int  add(long a,long b);
    	};
        
        @FunctionalInterface
    	public interface Empty extends Adder{
    
    	}
        @FunctionalInterface
    	public interface DefaultAddr extends Adder{
    		default int otherAddr(int a,int b){
    			return a+b;
    		}
    	}
        
        public static void main(String[] args) {
        	//1.lambda表达式替代匿名内部类
            WhereToUsage();
            //通过栗子了解Predicate的用法:过滤指定颜色和重量的苹果
            List<Apple> greenList = filter(list, apple -> apple.getColor().equals("green"));
    	    System.out.println(greenList);
          //2.除Predicate<T>之外,还有细化的Predicate,如
            // BiPredicate<T,U>( boolean test(T t, U u);), IntPredicate(boolean test(int value);),
     	    // LongPredicate(boolean test(long value);), DoublePredicate(boolean test(double value);)
            List<Apple> weightList = filterByWeight(list,value -> value>100);
    		System.out.println(weightList);
            //return返回值,表达式需要使用{}隔离
            List<Apple> result = filterByBiPredicate(list,(color,weight)->{return color.equals("green")&&weight>100;});
            List<Apple> result2 = filterByBiPredicate(list,(color,weight)->(color.equals("green")&&weight>100));
    		System.out.println(result);
    		System.out.println(result2);
            //3.Consumer的用法
            //Consumer<T> (void accept(T t);)
    		//BiConsumer<T,U>(void accept(T,U);)
             simpleTestConsumer(list,a-> System.out.println(a));
    		simpleBiConsumer(list,(a,b)-> System.out.println("颜色为:"+a+"重量为:"+b));
    		simpleBiConsumer2(list,(a,b)-> System.out.println("信息为:"+a.getWeight()+"颜色为:"+a.getColor()));
            
            //4.Function的用法,传入一个苹果,传出的苹果String,两种类型可相同可不同
            Apple apple = Apple.builder().weight(120).color("red").build();
            String result3 = testFunction(apple, a -> a.toString());
            System.out.println(result3);
            
            String color = "红色";
    		long weight = 105L;
    		testBiFunction(color,weight,(c,w)->new Apple(c,w));
             compute(3,r -> r*r);
    		 compute(3,r -> r+r);
            //Function中,compose是其默认方法,接受一个function作为参数,将参数function的执行结果
            //作为参数给调用的function,以此实现两个function组合的功能
    		int b = compute(2,r -> r*r,w -> w+w);  //(2+2)*(2+2) = 16
            
            //Function andThen,接收一个function作为参数,与compse不同的是,先执行本身的apply方法,
    		// 将执行的结果作为参数给参数中的function。
    		andThen(4,r -> r+1, w -> w*2);  //(4+1)*2 = 10
            
            IntFunction<Double> f = i -> i * 100d;
    		Double result4 = f.apply(10);
    
    		Supplier<String> s = String::new;
    		System.out.println(s.getClass());
            
            
            //5.()->expression用法
            createApple(() -> new Apple("green",120));
            int i = 0;
    		Runnable r = new Runnable() {
    			@Override
    			public void run() {
    				//i++;
    				System.out.println(i);
    			}
    		};
            Runnable  r2 = () -> System.out.println(i);
        }
        
        private static Apple createApple(Supplier<Apple> supplier){
    		return supplier.get();
    	}
        
        public static int andThen(int a,Function<Integer,Integer> function,Function<Integer,Integer> function2){
    		return function.andThen(function2).apply(a);
    	}
        
        private static int compute(int a,Function<Integer,Integer> function,Function<Integer,Integer> function2){
    		return function.compose(function2).apply(a);
    	}
    
        private static int compute(int a,Function<Integer,Integer> function){
    		return function.apply(a);
    	}
        	//两个输入,一个输出
    	private static Apple testBiFunction(String color,Long weight,BiFunction<String,Long,Apple> function){
    		return function.apply(color,weight);
    	}
        	//一个传入->一个传出
    	private static String testFunction(Apple apple,Function<Apple,String> function){
    		return function.apply(apple);
    	}
    
        private static void WhereToUsage(){
            Runnable r = () -> System.out.println(Thread.currentThread().getName());
    		Runnable r2 = new Runnable() {
    			@Override
    			public void run() {
    				System.out.println(Thread.currentThread().getName());
    			}
    		};
    		process(r);
    		process(r2);
    		process(()->{ System.out.println(Thread.currentThread().getName()); });
        }
        
        private static void process(Runnable r){
            r.run();
        }
        
       private static List<Apple> filter(List<Apple> source, Predicate<Apple> predicate){
    		List<Apple> result =  new ArrayList<>();
    		for (Apple apple : source) {
    			if(predicate.test(apple)){
    				result.add(apple);
    			}
    		}
    		return result;
    	}
        
        private static List<Apple> filterByWeight(List<Apple> source, LongPredicate predicate){
            List<Apple> result = new ArrayList<>();
            for (Apple apple : source) {
                if(predicate.test(apple.getWeight())){
                    result.add(apple);
                }
            }
            return result;
    	}
        
    	private static  List<Apple> filterByBiPredicate(List<Apple> source, BiPredicate<String,Long> predicate){
    		List<Apple> result = new ArrayList<>();
    		for (Apple apple : source) {
    			if(predicate.test(apple.getColor(),apple.getWeight())){
    				result.add(apple);
    			}
    		}
    		return result;
    	}
        
     	private static void simpleTestConsumer(List<Apple> source,Consumer<Apple> consumer){
    		for (Apple apple : source) {
    			consumer.accept(apple);
    		}
    	}
    	private static void simpleBiConsumer(List<Apple> source,BiConsumer<String,Long> consumer){
    		for (Apple apple : source) {
    			consumer.accept(apple.getColor(),apple.getWeight());
    		}
    	}
        
        private static void simpleTestConsumer(List<Apple> source,Consumer<Apple> consumer){
    		for (Apple apple : source) {
    			consumer.accept(apple);
    		}
    	}
        
        private static void simpleBiConsumer(List<Apple> source,BiConsumer<String,Long> consumer){
    		for (Apple apple : source) {
    			consumer.accept(apple.getColor(),apple.getWeight());
    		}
    	}
        
        	private static void simpleBiConsumer2(List<Apple> source,BiConsumer<Apple,String> consumer){
    		for (Apple apple : source) {
    			consumer.accept(apple,apple.getColor());
    		}
    	}
        
    }
    
  • lambda表达式之类型推导、方法引用、方法推导、组合lambda表达式

    public class MethodReference {
    
    	public static void main(String[] args) {
            //以下三种效果相同
    		Consumer<String> consumer = (s) -> System.out.println(s);
    		useConsumber(consumer,"Hello World !");
    
    		useConsumber(s -> System.out.println(s),"Hello World");
    
    		useConsumber(System.out::println,"Hello World");
            
            //排序,通过color的ascii码
    		List<Apple> list = Arrays.asList(new Apple("Green",110),
    				new Apple("Red",123),
    				new Apple("Yellow",180));
    		System.out.println(list);
            
            //sort方法底层:@FunctionalInterface public interface Comparator<T>{ boolean equals(Object obj);}
            list.sort((a1,a2) ->{
    			return a1.getColor().compareTo(a2.getColor());});
    		list.sort((a1,a2)->a1.getColor().compareTo(a2.getColor()));
            
            list.stream().forEach(a->System.out.println(a));
    		list.stream().forEach(System.out::println);
            
             //什么时候需要函数推导
    		list.stream().forEach(a -> System.out.println(a)); //循环遍历,将list中数据比遍历出来
    		list.stream().forEach(System.out::println); //循环遍历,将list中数据比遍历出来
            
            //双冒号运算操作符是类方法的句柄,是lambda表达式的一种简写
    		/**
    		 *  x -> System.out.println(x) 简化为 System.out::println 的过程称之为 eta-conversion
    		 *  System.out::println 简化为 x -> System.out.println(x) 的过程称之为 eta-expansion
    		 *  举例:
    		 *  person -> person.getAge();可以替换为Person::getAge
    		 *  x -> System.out.println(x)可以替换成System.out::println
    		 *
    		 */
            
            /*BiFunction<String, Integer, Character> f2 = String::charAt;
    		Character c = f2.apply("hello",3);
    		System.out.println(c);*/
            
            //1.通过静态方法去创建:
    		int value = Integer.parseInt("123");
    		Function<String,Integer>  f = Integer::parseInt;
    		Integer apply = f.apply("123");
    		System.out.println(apply);
            
            //2.可以通过对象的一个实例方法去推断,如一个类方法
    		//需要一个类的成员方法,需要传入这个类本身
    		BiFunction<String,Integer,Character> f2 = String::charAt;
    		Character c= f2.apply("hello",3);
    		System.out.println(c);
    
    		test t = new MethodReference().new test();
    		BiFunction<test, Integer, Integer> getNumber = test::getNumber;
    		int result = getNumber.apply(t,5);
    		System.out.println(result);
            
            //3.可以使用对象存在一个实例方法去做取代
    		String string = new String("hello");
    		Function<Integer ,Character>  f3 =string::charAt;
    		Character c1 = f3.apply(2);
    
    
    		testFunction(string,a->a.length());
    		System.out.println(c1);
    
            //方法推导部分
    		//supplier<T>: T get(); one parameter
    		Supplier<String> supplier = String::new;
    		String s = supplier.get();
    		System.out.println(s);
    
    		//two parameters
    		BiFunction<String,Long,Apple> appleBiFunction = Apple::new;
    		Apple apple = appleBiFunction.apply("Red", 120l);
    		System.out.println(apple);
    
    		//three parameters
    		ThreeFunction<String,String,Long,ComplexApple> appleThreeFunction = ComplexApple::new;
    		ComplexApple complexApple = appleThreeFunction.apply("Red", "苹果", 120L);
    		System.out.println(complexApple);
    
    
    		List<Apple> list2 = Arrays.asList(new Apple("Green",110),
    				new Apple("Red",123),
    				new Apple("Yellow",180));
    		list2.sort(Comparator.comparing(Apple::getColor));
                           
    	}
    private class test{
        public int getNumber(int n){
            return n+1;
        }
    }    
    private static void testFunction(String str,Function<String,Integer> function){
    		function.apply(str);
    	}    
    private  static <T> void useConsumber(Consumer<T> consumer,T t){
    		consumer.accept(t);
    		consumer.accept(t);
    	}
    }
    
    
    
    @FunctionalInterface
    public interface ThreeFunction<T,U,K,R>{
    
    	R apply(T t,U u,K k);
    
    }
    
  • 源码放在这儿

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罚站的孩子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值