java8中的函数式编程(Runnable、Comparator和FileFilter接口)

1.lambda表达式(函数式编程)

当需要启动一个线程去完成任务时,通常会通过java.lang.Runnable接口来定义任务内容,并使用java.lang.Thread类来启动该线程。

代码如下:

  • 方法一

    //自定义一个线程类Thread2
    public class TreadT2 implements Runnable {
    @Override
    public void run() {
    for(int i=0;i<10;i++){
    //打印当前进程信息
    System.out.println(Thread.currentThread().getName()+
    " "+i);
    }
    }
    public static void main(String[] args) {
    TreadT2 t2 = new TreadT2();
    Thread thread = new Thread(t2,“小强”);
    Thread thread1 = new Thread(t2,“小李”);
    thread.start();
    thread1.start();
    }

  • 方法二

    public static void main(String[] arg){

          Runnable runnable = new Runnable() {
            @Override
            public void run() {               System.out.println(Thread.currentThread().getName() + "");        }
          };
    
     Thread t=new Thread(runnable);
     t.start();
     //start()开启线程
    }
    

对于方法二可以用lambda函数简化代码

面向对象的思想:

做一件事,找一个能解决这个事情的对象,调用对象的方法,完成事情

函数式编程的思想:

只要能获得结果,谁去做的,怎么做都不重要,重视的是结果,不重视过程

代码分析

注意:java中Thread类实现Object类并实现Runnable接口

对于Runnable的匿名内部类用法,可以分析出:

  • Thread类需要Runnable接口作为参数,其中的抽象run方法是用来指定线程任务内容的核心;

  • 为了省去定义一个RunnableImpl实现类的麻烦,不得不使用匿名内部类;

  • 必须覆盖重写抽象run方法、所有方法名称、方法参数、方法返回值不得再重写一遍;

  • 借助java8的全新语法,匿名内部类写法更简单
    public static void main(String[] arg){

    new Thread(()->System.out.println(Thread.current.getName()+" ")).satrt();
      //启动线程
      }
    /*
    *对比一下
    */
    Runnable runnable = new Runnable() {
              @Override
              public void run() {               System.out.println(Thread.currentThread().getName() + "");        }
            };
    
       Thread t=new Thread(runnable);
       t.start();
       //start()开启线程
    

    这段代码和刚才的执行效果是完全一样的,可以在1.8或更高的编译级别下通过。从代码的语义中可以看出:我们启动了一个线程,而线程任务的内容以一种更加简洁的形式被指定。
    不再有“不得不创建接口对象”的束缚,不再有“抽象方法覆盖重写”的负担,就是这么简单!
    匿名内部类的好处与弊端
    一方面,匿名内部类可以帮我们省去实现类的定义;另一方面,匿名内部类的语法——确实太复杂了!
    语义分析
    仔细分析该代码中的语义,Runnable接口只有一个run方法的定义:

    • public abstract void run();
      即制定了一种做事情的方案(其实就是一个函数):
    • 无参数:不需要任何条件即可执行该方案。
    • 无返回值:该方案不产生任何结果。
    • 代码块(方法体):该方案的具体执行步骤。

同样的语义体现在Lambda语法中,要更加简单:

() -> System.out.println("**********")
  • 前面的一对小括号即run方法的参数(无),代表不需要任何条件;
  • 中间的一个箭头代表将前面的参数传递给后面的代码;
  • 后面的输出语句即业务逻辑代码。

如同Runnable接口还有Comparator(compar抽象方法)和FileFilter(accept抽象方法),

2.Lambda的参数和有返回值

2.1 Comparator接口

当需要对一个对象数组进行排序时,Arrays.sort方法需要一个java.util.Comparator接口实例来指定排序的规则。假设有一个Person类,含有age、name属性:

public class Person {
    private  String name;
    private  int  age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

使用Comparator接口的写法

import java.util.Arrays;
import java.util.Comparator;

public class MenP {
    public static void main(String[] args) {
        // 本来年龄乱序的对象数组
        Person[] array = {
                new Person("古力娜扎", 19),
                new Person("迪丽热巴", 18),
                new Person("马尔扎哈", 20) };

        // 匿名内部类
     Comparator<Person> comp = new Comparator<Person>() {
           @Override
           public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
          }
       };
       Arrays.sort(array, comp); 
      // 第二个参数为排序规则,即Comparator接口实例
     
        for (Person person : array) {
            System.out.println(person);
        }
    }
}

代码分析

  • 为了排序,Array.sort方法需要排序规则,即Comparator接口的实例抽象方法compare是关键
  • 为了省去定义一个ComparatorImpl实现类的麻烦,不得不使用内名内部类
  • 必须重写抽象compare方法,所以方法名称、方法参数、方法返回值需要重写一次,不能写错

Lambda写法

import java.util.Arrays;
import java.util.Comparator;

public class MenP {
    public static void main(String[] args) {
        // 本来年龄乱序的对象数组
        Person[] array = {
                new Person("古力娜扎", 19),
                new Person("迪丽热巴", 18),
                new Person("马尔扎哈", 20) };

        // 匿名内部类(lambda)
     
       Arrays.sort(array, (a,b)->{
         return a.getAge()-b.getAge();
           }); 
      // 第二个参数为排序规则,即Comparator接口实例
     
        for (Person person : array) {
            System.out.println(person);
        }
    }
}

2.2 FileFilter

java.io.FilteFilter是个接口,时File的过滤器。该接口的对象可以传递给File类的listFiles(FileFilter)作为参数,接口中只有一个方法boolean accept(File pathname)测试pathname是否应该包含在当前File目录中,符合则返回true。

代码分析

  • 接口作为参数,需要传递子类对象,重写其中方法
  • accept方法,参数为File,表示当前File下所有的子文件和子目录。保留住了返回true,过滤掉返回false。规则:
    1、要么是Java文件。
    2、要么是目录,用于继续遍历

代码实现

import java.io.File;
import java.io.FileFilter;

public class fileFilter {
    public static void main(String[] args) {
        File file = new File("E:\\文件\\idea2018\\src");
        print(file);//调用自定义方法
      }
  //自定义方法
   public static void print(File file){
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
              //判断是Java文件或是目录,是则保存并返回true
                return pathname.getName().endsWith(".java")||pathname.isDirectory();
            }
        });
     //判断如果是文件打印文件路径,否则继续调用print方法
        for (File f:files){
            if (f.isFile()){
                System.out.println("文件名"+f.getAbsolutePath());
            }else{
                print(f);
            }
        }

    }
}

Lambda写法

public static void print(File file){
    /**
     *
     * lambda形式
      */

    File[] files = file.listFiles(f -> {
        return f.getName().endsWith(".java") || f.isDirectory();
    });

    for (File f:files){
            if (f.isFile()){
                System.out.println("文件名"+f.getAbsolutePath());
            }else{
                print(f);
            }
        }

    }

3.Lambda省略格式及使用前提

省略规则

在Lambda标准格式的基础上,使用省略写法的规则为:

  1. 小括号内参数的类型可以省略;
  2. 如果小括号内有且仅有一个参,则小括号可以省略;
  3. 如果大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及语句分号。

使用前提

但是使用时有几个问题需要特别注意:

  1. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。
    无论是JDK内置的Runnable、Comparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
  2. 使用Lambda必须具有上下文推断。
    也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能使用Lambda作为该接口的实例。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值