java8新特性(拉姆达表达式lambda)

java8新特性(拉姆达表达式lambda)一、函数式接口函数式接口(functionalinterface也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和java.util.Comparator都是典型的函数式接口。java8提供@FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

一、函数式接口

函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。
java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟机会自动判断, 但 最好在接口上使用注解@FunctionalInterface进行声明,以免团队的其他人员错误地往接口中添加新的方法。

Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现.

下面的接口就是一个函数式接口


@FunctionalInterface //添加此注解后,接口中只能有一个抽象方法。
public interface A { 
   
	void call();

}

二、lambda语法

包含三部分:
1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数
2、一个箭头符号:->
3、方法体,可以是表达式和代码块。

(parameters) -> expression 或者 (parameters) -> { statements; } 

通过下面的代码可以看到lambda表达式设计的代码更简洁,而且可读性更好。

public class Demo1 { 
   
	public static void main(String[] args) { 
   
		runThreadByLambda();
		runThreadByInnerClass();
	}

	public static void runThreadByLambda() { 
   
		/* Runnable就是一个函数式接口:他只有一个方法run()方法。 1、因为run()方法没有参数,所以 ->前面的()中不需要声明形参 2、run返回的是void,所以不需要return。 3、->后面写的代码其实就是定义在run方法内的代码。因为此处代码只有一行,所以{}也可以省略。如果此处多与一行,则无法省略。 */
		Runnable runnable = () -> System.out.println("这个是用拉姆达实现的线程");
		new Thread(runnable).start();
	}

	public static void runThreadByInnerClass() { 
   
		Runnable runnable = new Runnable() { 
   

			@Override
			public void run() { 
   
				System.out.println("这个是用内部类实现的线程");

			}
		};
		new Thread(runnable).start();
	}
}

三、方法引用

其实是lambda表达式的一种简化写法。所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是”::”,右边是相应的方法名。如下所示:

ObjectReference::methodName

一般方法的引用格式:

  1. 如果是静态方法,则是ClassName::methodName。如 Object ::equals
  2. 如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
  3. 构造函数.则是ClassName::new
public class Demo2 { 
   

	public static void main(String[] args) { 
   
		/* * 方法引用 */
		Runnable runnable = Demo2::run;
		new Thread(runnable).start();
	}
	
	public static void run(){ 
   
		System.out.println("方法引用的代码...");
	}
}

可以看出,doSomething方法就是lambda表达式的实现,这样的好处就是,如果你觉得lambda的方法体会很长,影响代码可读性,方法引用就是个解决办法

四、默认方法—接口改进

简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。

@FunctionalInterface
public interface A { 
   
	void call();

	default void fun() { 
   
		System.out.println("我是接口的默认方法1中的代码");
	}

	default void fun2() { 
   
		System.out.println("我是接口的默认方法2中的代码");
	}
}

为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口 添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了使接口没有引入与现有的实现不兼容发展。

java8中接口和抽象类的区别

形同点:
1.都是抽象类型;
2.都可以有实现方法(以前接口不行);
3.都可以不需要实现类或者继承者去实现所有方法,(以前不行,现在接口中默认方法不需要实现者实现)++
不同点
++1.抽象类不可以多重继承,接口可以(无论是多重类型继承还是多重行为继承);
2.抽象类和接口所反映出的设计理念不同。其实抽象类表示的是”is-a”关系,接口表示的是”like-a”关系;
3.接口中定义的变量默认是public static final 型,且必须给其初值,所以实现类中不能重新定义,也不能改变其值;抽象类中的变量默认是 default 型,其值可以在子类中重新定义,也可以重新赋值。++

总结:默认方法给予我们修改接口而不破坏原来的实现类的结构提供了便利,目前java 8的集合框架已经大量使用了默认方法来改进了,当我们最终开始使用Java 8的lambdas表达式时,提供给我们一个平滑的过渡体验。也许将来我们会在API设计中看到更多的默认方法的应用。

五、使用lambda改进的集合框架

5.1 集合中内部迭代

import java.util.ArrayList;
import java.util.List;

public class Demo3 { 
   
	public static void main(String[] args) { 
   
		List<User> users = new ArrayList<User>();
		users.add(new User(20, "张三"));
		users.add(new User(22, "李四"));
		users.add(new User(10, "王五"));

		users.forEach((User user) -> System.out.println(user.getAge()));
	}
}

5.2 Stream API

流(Stream)仅仅代表着数据流,并没有数据结构,所以他遍历完一次之后便再也无法遍历(这点在编程时候需要注意,不像Collection,遍历多少次里面都还有数据),它的来源可以是Collection、array、io等等。

流作用是提供了一种操作大数据接口,让数据操作更容易和更快。它具有过滤、映射以及减少遍历数等方法,这些方法分两种:中间方法和终端方法,“流”抽象天生就该是持续的,中间方法永远返回的是Stream,因此如果我们要获取最终结果的话,必须使用终点操作才能收集流产生的最终结果。区分这两个方法是看他的返回值,如果是Stream则是中间方法,否则是终点方法。

filter

在数据流中实现过滤功能是首先我们可以想到的最自然的操作了。Stream接口暴露了一个filter方法,它可以接受表示操作的Predicate实现来使用定义了过滤条件的lambda表达式。


import java.util.stream.Stream;

public class StreamDemo { 
   
	public static void main(String[] args) { 
   
		List<User> users = new ArrayList<User>();
		users.add(new User(20, "张三"));
		users.add(new User(22, "李四"));
		users.add(new User(10, "王五"));
		
		Stream<User> stream = users.stream();
		stream.filter(p -> p.getAge() > 20); //过滤年龄大于20的
	}
}

map

假使我们现在过滤了一些数据,比如转换对象的时候。Map操作允许我们执行一个Function的实现(Function<T,R>的泛型T,R分别表示执行输入和执行结果),它接受入参并返回。

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class StreamDemo { 
   
	public static void main(String[] args) { 
   
		List<User> users = new ArrayList<User>();
		users.add(new User(20, "张三"));
		users.add(new User(22, "李四"));
		users.add(new User(10, "王五"));
		
		Stream<User> stream = users.stream();
		 //所有的年龄大于20岁的User对象,转换为字符串50对象。现在流中只有字符串对象了。
		stream.filter((User user) ->  user.getAge() > 20).map((User user) -> { 
   return "50";});
	}
}

count

count方法是一个流的终点方法,可使流的结果最终统计,返回long

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collector;
import java.util.stream.Stream;

public class StreamDemo { 
   
	public static void main(String[] args) { 
   
		List<User> users = new ArrayList<User>();
		users.add(new User(20, "张三"));
		users.add(new User(22, "李四"));
		users.add(new User(10, "王五"));
		
		Stream<User> stream = users.stream();
		long count = stream.filter((User user) ->  user.getAge() >= 20).map((User user) -> { 
   return "50";})
		.count(); //返回流中元素的个数。
		System.out.println(count);	
	}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/191646.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • py 的 第 36 天「建议收藏」

    py 的 第 36 天「建议收藏」py 的 第 36 天

    2022年4月20日
    65
  • SpringBoot面试题及答案140道(2021年最新)

    SpringBoot面试题及答案140道(2021年最新)工作5年,处于找工作中ing。今年10月份刚刚整理出来的SpringBoot面试题,时间比较赶就没有按照模块分类排序了。总而言之,顺序比较乱,希望大家耐着性子看。如果实在介意,评论告知,我会视情况作修改的。另外如果大家觉得我找的SpringBoot面试题答案不够清晰,欢迎私信或者评论只出,我看到都会去修改的!1、SpringBoot有哪些优点?SpringBoot的优点有:1、减少开发,测试时间和努力。2、使用JavaConfig有助于避免使用XML。3、避免大量的Maven…

    2022年6月7日
    30
  • C语言教你怎么改变字体颜色

    C语言教你怎么改变字体颜色初学c的小伙伴可能已经对那个黑底白字的框有些厌倦了,不妨加点颜色,增加加可读性.

    2022年6月20日
    29
  • 递归算法 数据结构_数据结构中递归的定义

    递归算法 数据结构_数据结构中递归的定义一、什么是递归所谓递归,简单点来说,就是一个函数直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。引用知乎大佬的例子:我们可以把”递归

    2022年8月16日
    3
  • 0xc0000005发生访问冲突解决_更改兼容性还是c0000005

    0xc0000005发生访问冲突解决_更改兼容性还是c0000005该异常代号对应“访问冲突”,即内存的读写权限冲突,一般意味着代码中存在3种可能的问题……

    2022年10月3日
    0
  • mtk-keypad[通俗易懂]

    mtk-keypad[通俗易懂]一.keypad基本原理col作为输出,row作为输入检测,低电平有效colA~D轮流输出低电平,通过rol1~4上的低电平可以检测是哪个按键按下了但是存在这样的问题,A1,A2,B1同时按下,会造成B2按下的假象,称为鬼影(这3个键导通,colB打开,row2处也会检测到低电平)可以通过增加二极管的方式防止鬼影问题二.keypadporti…

    2022年5月4日
    61

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号