Java8新特性Lambda表达式详解

本文详细介绍了Lambda表达式的基本概念、无参/有参/多参形式,以及其与函数式接口的关系。重点讲解了如何在Java8中使用Lambda表达式创建线程、编写判断逻辑、比较器和过滤器,以及与匿名内部类的区别。
摘要由CSDN通过智能技术生成

第一章、Lambda表达式与函数式接口

1.1)Lambda 表达式是什么

1.1.1)无参数无返回值的Lambda方法

Lambda 表达式本质上是一个匿名方法,是JAVA8中提供的一种新的特性(一种新的表达方式,以前旧的写法换成新的写法,可以写出更简洁、更灵活的代码)。

我们以前定义一个方法总是想到方法的五要素:

修饰符 返回值类型 方法名(参数列){
方法体
}

//--------------------------------------------
//以前写个打印方法:
public void prin(){
System.out.println(" 打印这个Lambda啊");
}

将这个无参无返回值的方法用Lambda表达式翻新成Lambda语法的方法,语法格式如下:

最简单的三要素:
参数列表   操作符箭头   方法体
  ()         ->    {System.out.println(" 打印这个Lambda啊");}

//-------------------------------------------------------------
//注意注意这段代码无法运行
() -> { System.out.println(" 打印这个Lambda啊");}

1.1.2)有一个参数,并且无返回值

在这个基础上我们进行拓展丰富,在参数列表里放入参数,增加返回值。

//有一个参数,并且无返回值;注意这段代码无法运行
参数列表里放个参数a       操作符箭头        方法体
    (参数a)              ->        System.out.println(a);
   

1.1.3)多参,有返回值

在参数列表里放两个参数,有返回值。

//有两个以上的参数,有返回值,并且大括号方法体里头多条语句
Comparator com = (a, b) -> {
System.out.println("打印一下");  return Integer.compare(10, 11);
};

我们发现,Lambda语句前面多了个Comparator com = ,正是因为这段代码前面多了一个Comparator com 函数式接口,这段代码可以运行了。

1.2)函数式接口是什么

接口好理解,那什么是函数式接口呢?函数式接口是有且仅有一个抽象方法(不包含object中的方法)的接口。

注意:我们只需要关注抽象方法的个数,不用关注其他类型的方法个数。
我们可以用注解@FunctionalInterface 检测是否为函数式接口

@FunctionalInterface
interface MyFunctionalInterface {
	// 只能包含一个抽象方法
     void doSomething(); 
    // 函数式接口可以可以包含默认方法和静态方法
    default void doSomethingElse() {
        // 默认方法的实现
    }
    static void anotherMethod() {
        // 静态方法的实现
    }
}

public class Main {
    public static void main(String[] args) {
        // 检测是否为函数式接口
        boolean isFunctional = MyFunctionalInterface.class.isAnnotationPresent(FunctionalInterface.class);
        System.out.println("是函数式接口吗?" + isFunctional);
    }
}

第二章、使用Lambda

2.1)必须有一个函数式接口

看了第一章我们知道,Lambda表达式前面放普通接口是不行的,必须是Comparator 这种函数式接口。

//Consumer 是函数式接口
Consumer con = (x) -> System. out .println(x);
        con.accept( "这个可以运行打印了" );

2.2)省略规则

   1. 参数类型必须同时省略

   2. 一个参数时,参数的括号可省略

   3. 代码块里只有一句时,可省略大括号,分号和return

Comparator com = (x, y) -> Integer.compare(10, 13);

2.3)Lambda和匿名内部类比较

Lambda表达式虽然简洁,用()->就可以代替整个匿名内部类,但只能用于函数式接口。而匿名内部类却可以用于接口,抽象类或者普通类。举个函数式接口Runnable接口的例子:

  new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("这是匿名内部类里传了个Runnable的实现类对象");
        }
    }).start();

用Lambda

 new Thread(() -> System.out.println("好家伙这么简洁")).start();

第三章、具体使用举例

我们要明确:方法体才是关键所在,Lambda表达式方法体里的方法来自哪个函数式接口,这个函数式接口的抽象方法作用是什么,才能有明确的目的去写Lambda表达式,也就是我们说的:“解决什么问题”。

3.1)案例一,自己写简单Lambda表达式

1.自定义一个函数式接口,注意只能有一个抽象方法,

public interface Test {
//有且仅有一个抽象方法
    public String TestFunc(String test_str);
}

2.Lambda表达式:把字符串传入箭头符号右边的方法体

   Test test =(str)->{ System.out.println(str); return str;};
        String str=test.TestFunc("打印这个字符串");
        
   }

3.2)案例二,Lambda表达式创建线程(Runnable函数式接口)

明确作用和方法:

1.Runnable接口,Runnable 为非 Thread 子类的类提供了一种激活方式。把Runnable的实例传给Thread 实例并将自身作为运行目标,就可以运行实现 Runnable 的类而无需创建 Thread 的子类。

唯一的抽象方法run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法

// 匿名内部 类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名对象 传递线程任务.....");
            }
        }).start();

2.再用Lambda表达式写

//Lambda表达式 省略格式
//参数类型必须同时省略
//一个参数时,参数的括号可省略
//代码块里只有一句时,可省略大括号,分号和return  

new Thread(() -> System.out.println("Lambda表达式 启动线程...")).start();

3.3)案例三,Lambda表达式写判断型接口(Predicate函数式接口)

明确作用和方法:Predicate判断型接口,可以对数据进行条件的判断,返回判断的结果。

演示:1.第一步先创建集合list

  //先创建一个集合
ArrayList<Integer> list = new ArrayList<>();
  //使用addAl方法添加元素
    Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9);

2.用list调用removeIf()方法,

注意:因为removeIf()参数列表里需要传递的是函数式接口Predicate实例

所以我们可以在方法的括号里头,用上匿名内部类写法;在大括号里重写这个唯一的抽象方法。

 // 删除集合中的偶数  default boolean removeIf​(Predicate<? super E> filter) 删除满足给定谓词的此集合的所有元素。
        list.removeIf(new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return integer % 2 == 0;
            }
        });
        System.out.println(list);

3.在前面我们提到Predicate接口是函数式接口,所以我们自然可以用Lambda重写一次

//不省略格式
    list.removeIf( (Integer itgr) -> { return itgr % 2 == 0;});

//省略写法 
// 1.一个参数把括号和参数类型     省略
// 2.只有一条方法语句把大括号{}和; return 省略

    list.removeIf(  itgr -> itgr % 2 == 0);
//打印集合
    System.out.println(list);

3.4)Lambda表达式写比较器(Comparator函数式接口)

明确作用和方法:Comparator函数式接口,强行对某个对象 collection 进行整体排序 的比较函数。可以将 Comparator实例 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。

1.创建集合加入元素

 // 创建集合使用addAll()方法加入元素
 ArrayList<Integer> list = new ArrayList<>();
    Collections.addAll(list, 1, 3, 2, 4, 5, 7, 9, 8, 6);

    // 先用sort(list)方法进行  升序 排序
    Collections.sort(list);
    System.out.println(list);

2.注意:因为参数列表里需要传递的参数类型是函数式接口Comparator

所以我们可以在sort()方法的括号里头,用上匿名内部类写法;在里头重写这个唯一的抽象方法compare()

//匿名内部类  写降序排序,Collections.sort(List<T> list, Comparator<? super T> c)
        
Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

3.用Lambda重写一下

//lambda表达式写 降序排序
// Collections.sort(list,(Integer o1, Integer o2)->{ return o2 - o1;});
// 简化格式,两个参数类型一样省略参数类型但是括号不能省略,方法体只一条语句省略{};return
    Collections.sort(list,(o1,o2)->  o2 - o1);
     System.out.println(list);

3.5)Lambda表达式写过滤器(FileFilter函数式接口)

明确作用和方法:抽象路径名的过滤器。该接口的实例可以传递给File类的listFiles(FileFilter)方法。

1.先用匿名内部类写

 // 创建文件对象,文件路径是d:\\demo
        File file = new File("d:\\demo");
        // file调用listFiles()直接传入过滤器的实例和pathname,返回类型是数组
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //endsWith(".txt") 获取以.txt结尾,并且只要是文件,
                return pathname.getName().endsWith(".txt") && pathname.isFile();
            }
        });

2.用Lambda写

//这是未简化
File[] files1 = file.listFiles((File pathname)->{return pathname.isFile() && pathname.getName().endsWith(".txt");});

//简化格式后
        File[] files1 = file.listFiles( pathname -> pathname.isFile() && pathname.getName().endsWith(".txt") );

  • 20
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值