为了账号安全,请及时绑定邮箱和手机立即绑定

用Java8来进行函数式编程

标签:
Android

 这个标题有点意思

Java8的明显特点是通过默认接口定义、Lambda表达式、方法引用、函数式接口带来了函数式编程,这些功能的出现也改变了java多年来的一些习惯

 

接口定义增强:

这是一个极其毁三观的方式

java的接口一直是由全局常量和抽象方法组成,但是在Java8出现后,这一个形势就因此改变了…

场景:存在一个接口,而同时有2k个类实现了该接口,突然有一天需求更改,需在接口里添加一个方法,而所有实现该接口的子类该方法的实现是一样的,按照之前的方式,需在每一个子类复写该方法,so….你需要复制粘贴2k次

为了解决这个问题,default就诞生了

default示例

interface Formula {    double calculate(int a);    default double sqrt(int a) {        return Math.sqrt(a);
    }    //static方式    static void get(){
         system.out.println("...");
    }
}
Formula formula = new Formula() {
    @Override    public double calculate(int a) {        return sqrt(a * 100);
    }
};

formula.calculate(100);     // 100.0formula.sqrt(16);           // 4.0//static方式Formula.get();


除了用default定义方法,一旦使用了static定义方法意味着这个方法只可以直接由类名称调用。

另外还有一个重要概念:内部类访问方法参数的时候可以不加上final关键字

 

 Lambda表达式

lambda属于函数式编程的概念

传统的匿名内部类,Android中添加监听器的典型例子

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {    @Override
    public void onClick(View view) {
        Toast.makeText(MainActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show();
    }
});

这段代码好繁琐

这个代码认真一看,其实主要运用到的代码仅仅只有Toast使用的这一句,但由于java的面向对象语法,不得不嵌套更多内容

做法太过严谨,于是java8引入了函数式编程简化语法

怎么简化呢?

Lambda范例:

Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(v->Toast.makeText(MainActivity.this, "Button Clicked", Toast.LENGTH_SHORT).show());

长度减了一大半,使用了Lambda表达式大大简化了语法

道理我都懂,怎么使用?

Lambda语法三种形式

  • (参数)->单行语句;    () -> System.out.println(“hello”)

  • (参数)->{单行语句}; (String s) -> { System.out.println(s); }

  • (参数)->表达式     (int x, int y) -> x + y

范例:

  public void runnableTest() {        // 一个匿名的 Runnable
        Runnable r1 = new Runnable() {
            @Override            public void run() {
                System.out.println("Hello world one!");
            }
        };        // Lambda Runnable
        Runnable r2 = () -> System.out.println("Hello world two!");        // 执行两个 run 函数
        r1.run();
        r2.run();
    }

让我再举一个简化变得更短的例子

List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, (String a, String b) -> b.compareTo(a));//让他再变得更短些
Collections.sort(names, (a, b) -> b.compareTo(a));

嘿嘿,看明白了吗

当只有一个表达式时,那么会直接进行返回操作

 

 方法引用

以前更多的是在对象上使用引用,而java8多出的是方法引用

这是什么鬼?

待会再跟你解释.

方法引用需要使用 :: 关键字,这是java8才有的东东

接下来,让我们说说四种形式方法引用:

  • 引用静态方法:类名称 :: static 方法名称;

  • 引用某个对象的方法:实例化对象 :: 普通方法;

  • 引用特定类型的方法:特定类 :: 普通方法

  • 引用构造方法:类名称 :: new

例子:引用静态方法:

在String类里面有一个valueOf()方法:public static String valueOf(int x);

interface Inter<P,R>{
     public R zhuanhuan(P p);
}
public class Test{
     public static void main(String args[]){
         Inter<Integer,String> msg = String::valueOf;
         String str = msg.zhuanhuan(3000);
         System.out.println(str); // 3000
         //原始方法
         Inter<Integer, String> msg = new Inter<Integer, String>() {
        public String zhuanhuan(Integer p) {            return  String.valueOf(p);
        }
    };
         //lambda          Inter<Integer, String> msg =(p)->String.valueOf(p);
    }
}

通过

Inter<Integer,String> msg = String::valueOf;

让Inter的R方法拥有了valueOf的功能

卧槽,这….不就是传说中的直接复制敌人绝招嘛,

将String.valueOf()方法变为了Inter接口里的R()方法,

再来另外三个例子看看?

例子:引用普通方法:

@FunctionalInterface //此为函数式接口,只能定义一个方法interface Inter<P,R>{
     public R upper();
     //public void print();}public class Test{
     public static void main(String args[]){
          //要在实例化对象下使用          //hello是String的实例化对象          Inter<Integer,String> msg = "hello"::toUpperCase;
          String str = msg.Upper();
          System.out.println(str); // HELLO     }
}

此时我们应该有了疑问:

通过两个代码演示,如果要实现函数引用,接口里必须只存在一个方法。如果再来一个方法,方法不是无法引用了吗?如划线语句

    //public void print();

所以为了保证被引用接口里面只有一个代码,需加上注解@FunctionalInterface 此为函数式接口

之前引用的方式中,都是静态方法,

接下来我们试试引用普通方法需实例化

例子:引用特定类方法 ,比较方法public int compareTo(String anotherString);

interface Inter<P>{
     public int compare(P p1,P p2);
}public class Test{
     public static void main(String args[]){
          Inter<String> msg = String::compareTo;
          System.out.println(msg.compare("A","B")); // -1     }
}

与之前相比,方法引用前不再需要定义对象,而是可以理解为将对象定义在了参数上

例子:引用构造方法

又一个毁三观的功能

interface Inter<C>{
     public C create(String t,double p);
}class Book {
     private String title;
     private double price;
     public Book(String title,double price){
         this.title = title;
         this.price = price;
     }
     public String toString(){
         return "book name:"+this.title+",book price:"+this.price;
     }
}public class Test{
     public static void main(String args[]){
         Inter<Book> msg = Book::new;
         Book book = msg.create("java",20);
         System.out.println(book);//book name:java,book price:20     }
}

那为啥java8不定义这些接口直接给我们使用呢?

当然有啦

 

 函数式接口

jdk8提供了一个函数式接口包java.util.function,里面有众多的函数式接口,而其中最基础最常操作的有以下四个核心接口:

功能型接口:

  • public interface Function<T,R>{public R apply(T t);}

  • 接收一个参数 返回一个结果

  • 例如String.valueOf()

消费型接口:

  • public interface Consumer<T>{public void accept(T t);}

  • 接收参数 不返回结果

  • 例如System.out.println

供给型接口:

  • public interface Supplier<T>{public void get(T t);}

  • 不接收参数 返回结果

  • 例如String的toUpperCase()

断言型接口:

  • public interface Predicate<T>{public boolean test(T t);}

  • 判断操作使用

  • 例如String的equalsIgnoreCase()

说这些,来个例子?

public class Test{
     public static void main(String args[]){
          //功能型接口          Function<String,Boolean> fun = "hello"::startsWith;
          System.out.println(fun.apply("he"));          //true          //消费型接口          Consumer<String> cons = System.out::println;
          cons.accept("hello");                         //hello          //供给型接口          Supplier<Stirng> sup = "hello"::toUpperCase;
          System.out.println(sup.get());                //HELLO          //断言型接口          Predicate<String> pre ="hello"::equalsIgnoreCase;
          System.out.println(pre.test("Hello"));        //true              }
}

这几个接口包含的各种引用,也是函数式接口的代表,那么存在其他的众多接口中,都是这四个接口的扩展提升

 

So,这些就是Java8带来的新特性啦

多多实践有利掌握

原文链接:http://www.apkbus.com/blog-719059-63047.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消