java8新特性lambda表达式

lambda表达式:

可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

匿名——我们说匿名,是因为它不像普通的方法那样有一个明确的名称。
函数——我们说它是函数,是因为Lambda函数不像方法那样属于某个特定的类。但和方法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表。
传递——Lambda表达式可以作为参数传递给方法或存储在变量中。(行为参数)
简洁——无需像匿名类那样写很多模板代码。

总结:快速实现接口中的方法

1:基本语法

 使用lambda表达式实现配合Collections完成排序功能。
 对比,匿名内部类
 感受:lambda是快速实现接口中的方法
 
 自定义接口:里面只有一个抽象方法
 自定义测试类: 里面的某一个方法 参数为 接口类型
 main : 进行测试。

2:lambda表达式用法:

	1,没有参数,没有返回值
		()->{}
		注:如果大括号里只有一句代码 ()->代码   该代码不要;号结尾
	2,没有参数,有返回值
		()->{return 值;}
		 注:如果大括号里只有一句代码 ()->返回值  该代码不要;号结尾
	3,有一个参数,没有返回值
	   (a)->{System.out.println(a)}
		注:如果大括号里只有一句代码 (a)->代码   该代码不要;号结尾
	4,有一个参数,有返回值
	   (a)->{a++;return a;}
		注:如果大括号里只有一句代码 (a)->返回值    该代码不要;号结尾
		注:如果只有一个参数,()也可以不写。
			a->{};
	5,有两个参数,没有返回值
	   (a,b)->{a++;System.out.println(b);}
		注:如果大括号里只有一句代码 (a,b)->代码    该代码不要;号结尾
	6,有两个参数,有返回值
		(a,b)->{a++;return a;}
		注:如果大括号里只有一句代码 (a,b)->返回值    该代码不要;号结尾
		注:大括号里的代码需要打分号。就是普通正常代码。
		注:参数里面是不用谢参数类型的。

3:lambda中变量的问题:

lambda中可以使用成员变量,局部变量,但是使用过局部变量以后,该局部变量就必须为final,所以不能再修改了。

4:在函数式接口上使用lambda表达式

jdk8中新引入了几个函数式接口:

  1. 【boolean放回值,一个泛型参数】Predicate接口 test(T t)

接口定义了一个名叫test的抽象方法,它接受泛型T对象,并返回一个boolean。 boolean test(T
t);表示:t进行断言,返回true或者false,可以配合其他的方法使用,如filter();
Predicate接口是用来支持java函数式编程新增的一个接口,使用这个接口和lambda表达式就可以以更少的代码为API方法添加更多的动态行为。
还有两个默认方法 and or

   /*
   @FunctionalInterface
   interface Predicate<T>{
	boolean test(T t);
   }
   */
   接口应用:
	   public class LambdaTest4 {
		 public static void filter(List<String> languages, Predicate<String> condition) {  
			for(String name: languages) {  
			   if(condition.test(name)) {  
				  System.out.println(name + " ");  
			   }  
			}  
		 }  
		 public static void main(String[] args) {
			List<String> languages = Arrays.asList("Java", "html5","JavaScript", "C++", "hibernate", "PHP");
			
			//开头是J的语言
			filter(languages,(String name)->name.startsWith("J"));
			//5结尾的
			filter(languages,(String name)->name.endsWith("5"));
			
			//所有的语言
			filter(languages,(name)->true);
			//一个都不显示
			filter(languages,(name)->false);
			//显示名字长度大于4
			filter(languages,(name)->name.length()>4);
			System.out.println("-----------------------");
			//名字以J开头并且长度大于4的
			Predicate<String> c1 = (name)->name.startsWith("J");
			Predicate<String> c2 = (name)->name.length()>4;
			filter(languages,c1.and(c2));
			
			//名字不是以J开头
			Predicate<String> c3 = (name)->name.startsWith("J");
			filter(languages,c3.negate());
			
			//名字以J开头或者长度小于4的
			Predicate<String> c4 = (name)->name.startsWith("J");
			Predicate<String> c5 = (name)->name.length()<4;
			filter(languages,c4.or(c5));
			
			//名字为Java的
			filter(languages,Predicate.isEqual("Java"));
			
			//判断俩个字符串是否相等
			boolean test = Predicate.isEqual("hello").test("world");
			System.out.println(test);
		 }
   
   源代码解析:
		default Predicate<T> and(Predicate<? super T> other) {
		Objects.requireNonNull(other);
		return (t) -> test(t) && other.test(t);
		   }
  1. 【一个放回值,一个参数】Function<T, R> 接口 R apply(T t); 有参数有返回值
    参数 返回值
    接收T对象,返回R对象
    表示接受一个参数并产生结果的函数。

      /*@FunctionalInterface
       interface Function<T, R>{
     	R apply(T t);
       }*/
      接口应用:  
       public class LambdaTest6 {
     	public static <T, R> List<R> map(List<T> list,Function<T, R> f) {
     	  List<R> result = new ArrayList<>();
     	  for(T s: list){
     		result.add(f.apply(s));
     	  }
     	  return result;
     	}
     	public static void main(String[] args) {
     	  List<Integer> list = map(
     		Arrays.asList("lambdas","in","action"),
     		(String s) -> s.length()
     	  );
     	  System.out.println(list);// [7, 2, 6]
     	}
       }
    
  2. 【一个返回值,没有参数】Supplier接口 T get(); 没参数有返回值
    返回值
    代表结果供应商。
    没有要求每次调用供应商时都会返回新的或不同的结果。

       /*@FunctionalInterface
        interface Supplier<T>{
     	T get();
        }*/
        接口应用:
        public class LambdaTest7 {
     		   
     	  public static void main(String[] args) {
     		//生成一个八位的随机字符串
     		Supplier<String> f = ()->{
     			String base = "abcdefghijklmnopqrstuvwxyz0123456789";     
     			Random random = new Random();     
     			StringBuffer sb = new StringBuffer();     
     			for (int i = 0; i < 8; i++) {  
     			   //生成[0,base.length)之间的随机数
     			   int number = random.nextInt(base.length());     
     			   sb.append(base.charAt(number));     
     			}     
     			return sb.toString();   
     		};
     		System.out.println(f.get());	
     	  }
        }
    
  3. 【没有返回,一个参数】Consumer 接口 void accept(T t); 有参数没返回值
    参数 对给定的参数执行此操作
    这个接口,接收一个泛型的参数T,然后调用accept,对这个参数做一系列的操作,没有返回值;

     接口应用:
        public class LambdaTest5 {
     	  public static <T> void forEach(List<T> list, Consumer<T> c){
     		for(T i: list){
     		  c.accept(i);
     		}
     	  }
     	  public static void main(String[] args) {
     		forEach(
     		  Arrays.asList(1,2,3,4,5),
     		  (Integer i) -> System.out.println(i)
     		);
     	  }
        }
        
        
     另外需要注意的接口: 其用法和上面介绍的接口使用方式类同		
    
  4. 【一个返回值,两个参数】BiFunction<T, U, R>接口
    R apply(T t, U u)
    将一个T和一个U输入,
    返回一个R作为输出

  5. 【一个返回值,两个参数】BinaryOperator接口
    T apply(T t, T t)
    将两个T作为输入,
    返回一个T作为输出
    BinaryOperator接口继承了BiFunction接口

  6. 【没有返回值,两个参数】BiConsumer<T, U>接口
    void accept(T t, U u)
    将俩个参数传入,
    没有返回值

    5,java常用的函数式编程接口使用:
    1. 比较器
    2. 实现线程
    3. 绑定事件
    4. 集合数据排序

类型推断:

你还可以进一步简化你的代码。
Java编译器会从上下文(目标类型)推断出用什么函数式接口来配合Lambda表达式,这意味着它也可以推断出适合Lambda的签名,
因为函数描述符可以通过目标类型来得到。这样做的好处在于,编译器可以了解Lambda表达式的参数类型,这样就可以在Lambda语法
中省去标注参数类型。 List list = new ArrayList<>();

lambda表达式:

方法引用:简化lambda,重复利用已有的代码
方法引用让你可以重复使用现有的方法定义,并像Lambda一样传递它们。
方法引用可以被看作仅仅调用 【特定方法的Lambda】 的一种快捷写法。
当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面。

1,引用构造器
	Supplier<类名> 变量名 = 类名::new
	Student stu = 变量名.get();

2,引用有参数构造器
	BiFunction<参数1, 参数2, 类名>  bf = 类名::new;
	类名 变量名 = bf.apply(值1,值2);

3,引用数组构造器
	IntFunction<int[]> arrayMaker = int[]::new;
	int[] array = arrayMaker.apply(10);

4,引用静态方法
	函数接口类型 变量名 = 类名::静态方法名

5,普通方法的引用:
	函数接口类型 变量名 = 对象::方法名;

6,实例方法引用
	类名::方法名A;
	将lambda的参数 直接当做 A方法的参数
	
	这种写法,不讨论返回值的问题。有就自动返回。
    1,如果lambda的参数正好和::后面方法A的参数一样,那么就是调用::后面的方法A,把lambda的参数传进去
        // R apply(T t);
			Consumer<String> f = System.out::println;
			Consumer<String> f1 = (t)->{System.out.println(t);};
	
		// void accept(T t, U u);
			BiConsumer<Integer,Integer> bc = (a,b)->{Math.max(a, b);};
			BiConsumer<Integer,Integer> bc1 =  Math::max;

    2,如果lambda的参数 比::后面方法A的参数多,那么就是第一个参数调用::后面方法A,把lambda剩下的参数传入::后面的方法A
		// R apply(T t);
			Function<String,String> fun1 = String::toUpperCase;
			Function<String,String> fun = (t)->t.toUpperCase();
		
		// void accept(T t, U u);
			BiConsumer<String,Integer> bc = String::substring;
			BiConsumer<String,Integer> bc1 = (a,b)->{a.substring(b);};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值