创建一个新的线程,指定线程要执行的任务
- package demo01;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo01
- * @ClassName: Test01
- * @Author: 王振华
- * @Description:
- * @Date: 2022/7/19 19:03
- * @Version: 1.0
- */
- public class Test01 {
- public static void main(String[] args) {
- My my = new My();
- Thread t1 = new Thread(my);
- t1.start();
-
- //匿名内部类
- Runnable task = new Runnable() {
- @Override
- public void run() {
- System.out.println("这是使用匿名内部类方法时的任务对象");
- }
- };
- Thread t2 = new Thread(task);
- t2.start();
-
-
- }
- }
-
- class My implements Runnable{
-
- @Override
- public void run() {
- System.out.println("自定义任务接口类");
- }
- }
代码分析:
* 1.Thread类需要一个Runnable接口作为参数,其中的抽象方法run方法是用来指定线程任务内容的核心
* 2.为了指定run方法体,不得不需要Runnable实现类
* 3.为了省去定义一个Runnable的实现类,不得不使用匿名内部类
* 4.必须覆盖重写抽象的run方法,所有的方法名称,方法参数,方法返回值不得不都重写一遍,而且不能出错
* 5.而实际上,我们只在乎方法体中的代码
Lambda表达式是一个匿名函数,可以理解为一段可以传递的代码
- //lambda表达式
- Thread t3 = new Thread(()->{
- System.out.println("这是使用lambda表达式完成的");
- });
- t3.start();
前提:必须是函数式接口。
Lambda表达式的优点:简化了匿名内部类的使用,语法更加简单。
匿名内部类语法冗余,体验了Lambda表达式后,发现Lambda表达式是简化匿名内部类的一种方式。
概念:
Lambda表达式:特殊的匿名内部类,语法更加简洁
Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递
语法:
<函数式接口> <变量名> = (参数1,参数2...) -> {
//方法体
};
格式说明:
注意:函数式接口:接口中只有一个抽象方法.
- package demo02;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo02
- * @ClassName: Test02
- * @Author: 王振华
- * @Description:
- * @Date: 2022/7/19 19:13
- * @Version: 1.0
- */
- //无参无返回值的Lambda表达式
- public class Test02 {
- public static void main(String[] args) {
- //匿名内部类
- /* Swimmable swimmable = new Swimmable() {
- @Override
- public void swimming(String name) {
- System.out.println("这是使用匿名内部类的方式");
- }
- };
- fun(swimmable);*/
-
- //lambda表达式
- fun(name -> {
- System.out.println("这是使用lambda表达式"+name);
- });
- }
- public static void fun(Swimmable s){
- s.swimming("郭富城");
- }
- }
-
- //函数式接口
- interface Swimmable{
- public void swimming(String name);
- }
下面举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:
public abstract int compare(T o1, T o2);
当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。
- package demo02;
-
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.List;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo02
- * @ClassName: Test03
- * @Author: 王振华
- * @Description:
- * @Date: 2022/7/19 19:26
- * @Version: 1.0
- */
- //有参有返回值的Lambda表达式
- public class Test03 {
- public static void main(String[] args) {
- List
list = new ArrayList<>(); - list.add(new Person("张三",20,158));
- list.add(new Person("李四",12,178));
- list.add(new Person("王五",30,167));
- list.add(new Person("赵六",15,184));
-
- //对集合中的元素进行排序 按照年龄从大到小
- //Collections: 集合的工具类 //传统做法:Comparator: 排序规则接口
- Collections.sort(list, new Comparator
() { - //int: 0表示新加的元素和集合中原来的比对的相同
- // //1: o2比o1大
- // //-1: o2比o1小
- @Override
- public int compare(Person o1, Person o2) {
- return o1.getAge()-o2.getAge();
- }
- });
-
- for(Person person : list){
- System.out.println(person);
- }
-
- System.out.println("=================================================");
-
- //使用Lambda表达式 按年龄从小到大
- Collections.sort(list,(o1,o2)->{return o2.getAge()- o1.getAge();});
-
- for(Person person : list){
- System.out.println(person);
- }
-
- }
- }
-
- class Person{
- private String name;
- private int age;
- private int height;
-
- public Person() {
- }
-
- public Person(String name, int age, int height) {
- this.name = name;
- this.age = age;
- this.height = height;
- }
-
- @Override
- public String toString() {
- return "Person{" +
- "name='" + name + '\'' +
- ", age=" + age +
- ", height=" + height +
- '}';
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public int getHeight() {
- return height;
- }
-
- public void setHeight(int height) {
- this.height = height;
- }
- }


内置函数式接口的由来
- package demo03;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo03
- * @ClassName: Test03
- * @Author: 王振华
- * @Description:
- * @Date: 2022/7/19 19:43
- * @Version: 1.0
- */
- public class Test03 {
- public static void main(String[] args) {
- int[] arr = {2,2,3,4,56,8};
- fun((arr1)->{
- int sum = 0;
- for(int n : arr1){
- sum += n;
- }
- System.out.println("数组的和:"+sum);
- },arr);
- }
-
- public static void fun(Operater operater,int[] arr){
- operater.getSum(arr);
- }
- }
- @FunctionalInterface
- interface Operater{
- //求数组的和
- public abstract void getSum(int[] arr);
- }
分析
我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。
常见得函数式接口
java.util.function保存

T:表示参数的泛型
有参数,无返回值。
- package demo04;
-
- import java.util.function.Consumer;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo04
- * @ClassName: Test01
- * @Author: 王振华
- * @Description: 消费型接口
- * @Date: 2022/7/19 19:50
- * @Version: 1.0
- */
- public class Test01 {
- public static void main(String[] args) {
- fun((t)->{
- System.out.println("花费了"+t+"元");
- },1000);
- }
-
- //调用某个方法时,该方法需要的参数为接口类型,这时就应该能想到Lambda
- public static void fun(Consumer
consumer,double money) { - consumer.accept(money);
- }
- }
T:表示返回结果的泛型
无参数,有返回值
- package demo04;
-
- import java.util.Random;
- import java.util.function.Supplier;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo04
- * @ClassName: Test02
- * @Author: 王振华
- * @Description: 供给型接口
- * @Date: 2022/7/19 19:56
- * @Version: 1.0
- */
- public class Test02 {
- public static void main(String[] args) {
- //0-9的随机整数
- fun(()->{return new Random().nextInt(10);
- });
- }
- public static void fun(Supplier
supplier) { - Integer s = supplier.get();
- System.out.println(s);
- }
- }
T: 参数类型的泛型
R: 函数返回结果的泛型
有参数,有返回值。
例子: 传入一个字符串把小写转换为大写。
- package demo04;
-
- import java.util.Locale;
- import java.util.function.Function;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo04
- * @ClassName: Test03
- * @Author: 王振华
- * @Description: 函数型接口
- * @Date: 2022/7/19 20:01
- * @Version: 1.0
- */
- public class Test03 {
- public static void main(String[] args) {
- fun((t)->{
- //转成大写
- return t.toUpperCase();
- },"hello world");
- }
-
- public static void fun(Function
function,String msg) { - String apply = function.apply(msg);
- System.out.println(apply);
- }
- }
T: 参数的泛型
boolean test(T t);
当传入一个参数时,需要对该参数进行判断时,则需要这种函数。
- package demo04;
-
- import java.util.function.Predicate;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo04
- * @ClassName: Test04
- * @Author: 王振华
- * @Description: 断言型接口
- * @Date: 2022/7/19 20:04
- * @Version: 1.0
- */
- public class Test04 {
- public static void main(String[] args) {
- //判断字符串的长度是否大于3,大于为true,否则相反
- fun((t)->{return t.length()>3;},"会当凌绝顶");
- }
-
- public static void fun(Predicate
predicate,String msg) { - boolean test = predicate.test(msg);
- System.out.println(test);
- }
- }
- package demo05;
-
- import java.util.function.Consumer;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo05
- * @ClassName: Test01
- * @Author: 王振华
- * @Description: Lombda的冗余
- * @Date: 2022/7/19 20:14
- * @Version: 1.0
- */
- public class Test01 {
- public static void main(String[] args) {
- fun((t)->{
- String s1 = t.toUpperCase();
- System.out.println(s1);
- },"hello world");
- }
-
- public static void fun(Consumer
consumer,String msg) { - consumer.accept(msg);
- }
-
- public static void toUpperCase(String s){
- String s1 = s.toUpperCase();
- System.out.println(s1);
- }
- }
分析:
我们发现toUpperCase方法和Consumer消费型接口中的代码体此时一致,我们重复写会使代码冗余。
如果我们在Lambda中所指定的功能,已经有其他方法存在相同方案,那是否还有必要再写重复逻辑?可以直接“引 用”过去就好了:---方法引用。
- package demo05;
-
- import java.util.function.Consumer;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo05
- * @ClassName: Test01
- * @Author: 王振华
- * @Description:
- * @Date: 2022/7/19 20:14
- * @Version: 1.0
- */
- public class Test01 {
- public static void main(String[] args) {
- fun((t)->Test01.toUpperCase(t),"hello world");
- fun(Test01::toUpperCase,"hello world"); //这两种 方法是一样的
- }
-
- public static void fun(Consumer
consumer,String msg) { - consumer.accept(msg);
- }
-
- public static void toUpperCase(String s){
- String s1 = s.toUpperCase();
- System.out.println(s1);
- }
- }
请注意其中的双冒号 :: 写法,这被称为“方法引用”,是一种新的语法。

方法引用的分类

- package demo06;
-
- import java.util.ArrayList;
- import java.util.Comparator;
- import java.util.List;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo06
- * @ClassName: Test06
- * @Author: 王振华
- * @Description: 静态方法引用
- * @Date: 2022/7/19 21:23
- * @Version: 1.0
- */
- public class Test06 {
- public static void main(String[] args) {
- List
list = new ArrayList<>(); - list.add(1);
- list.add(3);
- list.add(2);
- list.add(6);
- list.add(4);
-
- //Comparator
comparator = ((o1, o2) -> o1-o2); -
- //Comparator
comparator = ((o1, o2) -> Integer.compare(o1,o2)); - //调用了Integer类的静态方法compare方法
- Comparator
comparator = Integer::compare; - list.sort(comparator);
- System.out.println(list);
- }
- }
实例方法引用,顾名思义就是调用已经存在的实例的方法,与静态方法引用不同的是类要先实例化,静态方法引用类无需实例化,直接用类名去调用。
- package demo07;
-
- import java.time.Period;
- import java.util.Arrays;
- import java.util.Comparator;
- import java.util.function.Supplier;
-
- /**
- * @ProjectName: jdk1.8_1
- * @Package: demo07
- * @ClassName: Test07
- * @Author: 王振华
- * @Description: 实例方法引用
- * @Date: 2022/7/19 21:31
- * @Version: 1.0
- */
- public class Test07 {
- public static void main(String[] args) {
- People[] peoples = {new People("张三",15),new People("李四",12),new People("王五",58),new People("赵六",20)};
- //该数组进行排序---年龄排序int compare(T o1, T o2);
- //Comparator
comparator = (o1, o2) -> o1.getAge()-o2.getAge(); -
- //如果在lambda表达式中有且仅有一条语句,而且这条语句是对方法的调用。这时可以考虑使用方法引用
- //Comparator
comparator = (o1,o2)-> People.compare(o1,o2); - Comparator
comparator = People::compare; - Arrays.sort(peoples,comparator);
- System.out.println(Arrays.asList(peoples));
-
- People p=new People("李四",25);
-
- //在这个lambda表达式中只有一条语句,而且这条语句又是调用了某个方法
- //Supplier
s=()-> p.getName(); - Supplier
s=p::getName; - fun(s);
- }
- public static void fun(Supplier
supplier) { - String s = supplier.get();
- System.out.println("结果为:"+s);
- }
- }
- class People{
- private String name;
- private int age;
-
- public People(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "People{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
-
- public static int compare(People p1, People p2){
- return p1.getAge()-p2.getAge();
- }
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
- }