java8 (jdk 1.8) 新特性 ——初步认识

1. 什么是lambda?

目前已知的是,有个箭头  ->

说一大段官方话,也没有任何意义

我们直接看代码:

之前我们创建线程是这样的

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("run。。。。。。");
}
};
runnable.run();

用lambda:

    Runnable run2 = () -> System.out.println("run。。。。。。");
run2.run();

  

是不是感觉特别离谱,看不懂

别急,还有更离谱的

很常见的一个例子,比较两个整数的大小

之前是这样写的

        Comparator<Integer> myCom = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1, o2);
}
}; int compare = myCom.compare(12, 20);
int compare1 = myCom.compare(20, 12);
int compare2 = myCom.compare(20, 20);
System.out.println(compare);
System.out.println(compare1);
System.out.println(compare2);
}

  

用lambda:

        Comparator<Integer> myCom = (o1, o2) -> Integer.compare(o1, o2);

        int compare = myCom.compare(12, 20);
int compare1 = myCom.compare(20, 12);
int compare2 = myCom.compare(20, 20);
System.out.println(compare);
System.out.println(compare1);
System.out.println(compare2);

  甚至还可以这样 (这个是方法引用)

 Comparator<Integer> myCom = Integer::compare;

        int compare = myCom.compare(12, 20);
int compare1 = myCom.compare(20, 12);
int compare2 = myCom.compare(20, 20);
System.out.println(compare);
System.out.println(compare1);
System.out.println(compare2);

  

第一个数比第二个数

大 :返回 1

小:返回 -1

相等:返回 0

刚接触是不是黑人问号,这是什么玩意

很好,到这,你认识到了lambda 一个缺点,可阅读性差 ,优点 代码简洁

小结:看到 -> lambda           看到 : : 方法引用

2.  lamdba 语法

  • 基本语法

1.  箭头操作符  ->  或者叫做lambda 操作符

2.  箭头操作符将lambda 表达式拆分成两部分

左侧:Lambda 表达式的参数列表

右侧:Lambda 表达式中所需执行的功能  , 即 Lambda 体

3. 语法格式

语法格式1:无参数,无返回值 

  •  () -> system.out.println("Hello Lambda")
    

      

    前边线程的那个例子就是

语法格式2:有一个参数 无返回值

(x)-> System.out.println(x);

  

若只有一个参数可以省略不写

 x-> System.out.println(x);

  

之前的写法,没有使用lambda

 Consumer<String> consumer = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("输出的值:"+s);
}
}; consumer.accept("今天不想emo了");

  

使用lambda

 Consumer<String> consumer = s -> System.out.println("输出的值:"+s);

        consumer.accept("今天不想emo了");

 

语法格式3:有两个以上参数 ,并且lambda体有多条语句,有返回值

   Comparator<Integer> myCom = (o1, o2) -> {
System.out.println("其他语句");
return Integer.compare(o1, o2);
};

  

语法格式4  lambda体中只有一条语句,return 和 大括号都可以省略不写

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

  有没有发现所有的参数,都没有参数类型,之前我们写函数的时候可是要带上参数类型的

语法格式5  lambda表达式参数列表的数据类型可以省略不写,因为JVM编译器通过上下文编译推断出数据类型——类型推断 

4. 函数式接口

不管上面哪一种语法格式,lambda都是需要函数式接口的支持

 函数式接口:接口中只有一个抽象方法的接口 称为函数式接口

可以使用一个注解@FunctionalInterface 修饰,可以检查是否是函数式接口

我们可以看看Runnable  接口 的源码

完成的接口类代码如下

/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms
/ package java.lang;
/**
* The <code>Runnable</code> interface should be implemented by any
* class whose instances are intended to be executed by a thread. The
* class must define a method of no arguments called <code>run</code>.
* <p>
* This interface is designed to provide a common protocol for objects that
* wish to execute code while they are active. For example,
* <code>Runnable</code> is implemented by class <code>Thread</code>.
* Being active simply means that a thread has been started and has not
* yet been stopped.
* <p>
* In addition, <code>Runnable</code> provides the means for a class to be
* active while not subclassing <code>Thread</code>. A class that implements
* <code>Runnable</code> can run without subclassing <code>Thread</code>
* by instantiating a <code>Thread</code> instance and passing itself in
* as the target. In most cases, the <code>Runnable</code> interface should
* be used if you are only planning to override the <code>run()</code>
* method and no other <code>Thread</code> methods.
* This is important because classes should not be subclassed
* unless the programmer intends on modifying or enhancing the fundamental
* behavior of the class.
*
* @author Arthur van Hoff
* @see java.lang.Thread
* @see java.util.concurrent.Callable
* @since JDK1.0
*/
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}

  

可以看到这里面就只有一个实现,有一个注解@FunctionalInterface ,说明它就是一个函数式接口,就可以进行lambda简写

来看 Comparator 也是一样 有@FunctionalInterface注解

 

这里可能就会有疑问,这边明明是有两个抽象方法,怎么是函数式接口呢?

别急 !!可以看到这边的注释, 说明这个equals 是 重写了超类 的 equals,本质上是对object 的重写,官方定义这样的抽象方法是不会被定义到 抽象接口数的 ,因此实际上只有一个抽象方法

我们自己可以试着定义 函数式接口,很简单

package com.test1.demo;

@FunctionalInterface
public interface MyFunc { void method(); }

  

好了,如果,写两个抽象接口会怎样?

可以看到注解报错了,所以注解用来校验作用就在这

 重申一遍,函数式接口:接口中只有一个抽象方法的接口 称为函数式接口

注解只是拿来校验的,方便我们一看就知道这是一函数式接口类,不然还得数个数,验证一下是不是只有一个

现在我也重写 equals ,可以看到并没有报错

5. java8 中内置四大核心函数式接口 

  •   Consumer<T> 消费型接口 

 //Consumer  消费型接口
@Test
public void testConsumer() {
cosumer(1000, (m) -> System.out.println("星期一" + m));
// 星期一1000.0
} public void cosumer(double m, Consumer<Double> con) {
con.accept(m);
}

  

  •  供给型接口  supplier<T>

@Test
public void testSupplier() {
List<Integer> numList = getNumList(10, () -> (int) (Math.random() * 100));
for (Integer integer : numList) {
System.out.println(integer); //100 以内10位随机整数
}
} // 需求:产生指定个数的整数放入集合中
public List<Integer> getNumList(int num, Supplier<Integer> su) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < num; i++) {
Integer integer = su.get();
list.add(integer);
}
return list;
}

  

  •  Function<T,R> 函数型接口

 @Test
public void FunctioStr(){
String c = getFunction("sbjikss", str -> str.toUpperCase());
System.out.println(c); //SBJIKSS
String sub = getFunction("sbjikss", str -> str.substring(2, 3));
System.out.println(sub);//j
} public String getFunction( String str, Function<String,String> f) {
return f.apply(str);
}

  

  • 断言型接口 Predicate<T>  

 public  void  tetPre(){
List<String> list = Arrays.asList("Hello","sss","xxxx","sjjss");
List<String> list1 = filterStr(list, (pre) -> pre.length() > 3);
for (String s : list1) {
System.out.println(s); // Hello xxxx sjjss
}
}
//需求:将满足条件字符串放入集合中
public List<String> filterStr(List<String> old , Predicate<String> pre ){
List<String> newList = new ArrayList<>();
for (String str : old) {
if (pre.test(str)){
newList.add(str);
}
}
return newList;
}

  

感谢阅读!!!

java8 (jdk 1.8) 新特性——Lambda的更多相关文章

  1. 乐字节-Java8新特性-Lambda表达式

    上一篇文章我们了解了Java8新特性-接口默认方法,接下来我们聊一聊Java8新特性之Lambda表达式. Lambda表达式(也称为闭包),它允许我们将函数当成参数传递给某个方法,或者把代码本身当作 ...

  2. Java8新特性-Lambda表达式是什么?

    目录 前言 匿名内部类 函数式接口 和 Lambda表达式语法 实现函数式接口并使用Lambda表达式: 所以Lambda表达式是什么? 实战应用 总结 前言 Java8新特性-Lambda表达式,好 ...

  3. JDK 5 ~ 10 新特性倾情整理!

    JDK 5 ~ 10 新特性倾情整理! 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了. 为了大家对JDK ...

  4. Java JDK 1.7 和 JDK 1.8 新特性

    0 引言 本文主要介绍 Java JDK 中 1.7 和 1.8 的新特性. 1 JDK 1.7 新特性 1. switch可以接受String类型: public class Switch { pu ...

  5. Java 8 新特性 - Lambda表达式

    Lambda表达式 vs 匿名类既然lambda表达式即将正式取代Java代码中的匿名内部类,那么有必要对二者做一个比较分析.一个关键的不同点就是关键字 this.匿名类的 this 关键字指向匿名类 ...

  6. 译文《全新首发JDK 16全部新特性》

    封面:洛小汐 译者:潘潘 JDK 8 的新特性都还没摸透,JDK 16 的新特性就提着刀来了. 郑重申明: 第一次冒险翻译专业领域的文献,可想而知,效果特别糟糕.一般翻译文献特别是 技术专业领域 的内 ...

  7. 【C++11】新特性——Lambda函数

    本篇文章由:http://www.sollyu.com/c11-new-lambda-function/ 文章列表 本文章为系列文章 [C++11]新特性--auto的使用 http://www.so ...

  8. JDK 14的新特性:更加好用的NullPointerExceptions

    JDK 14的新特性:更加好用的NullPointerExceptions 让99%的java程序员都头痛的异常就是NullPointerExceptions了.NullPointerExceptio ...

  9. JDK 14的新特性:instanceof模式匹配

    JDK 14的新特性:instanceof模式匹配 JDK14在2020年的3月正式发布了.可惜的是正式特性只包含了最新的Switch表达式,而Records,patterns,text blocks ...

  10. C#10新特性-lambda 表达式和方法组的改进

    C# 10 中对Lambda的语法和类型进行了多项改进: 1. Lambda自然类型 Lambda 表达式现在有时具有"自然"类型. 这意味着编译器通常可以推断出 lambda 表 ...

随机推荐

  1. 安装docker-compose--翻译

    Install Docker Compose 译文 安装 Docker Compose 你可以在macOS.Windows.64-bit Linux上运行 Compose 前提条件 Docker Co ...

  2. ORM增删改查并发性能测试2

    前言 上一篇<ORM增删改查并发性能测试>出现了点小失误,有的输出SQL日志的代码没有禁用,数据库连接字符串可能有问题.统一环境,统一代码后,重新写一篇. 这次重点是并发性能测试,真不是为 ...

  3. 使用traefik进行金丝雀发布

    文章转载自:https://mp.weixin.qq.com/s/nMMN7hAJK6SFn1V1YyxvHA 在 Traefik 2.0 中以服务负载均衡的形式进行了支持.可以将服务负载均衡器看成负 ...

  4. MySQL集群搭建(2)-主主从模式

    1 环境准备 上次我们搭建了主备架构,如下所示 这次我们的搭建目标是 具体配置信息 IP 系统 端口 MySQL版本 节点 读写 说明 192.168.41.83 Centos6.8 3306 5.7 ...

  5. Javascript 手写 LRU 算法

    LRU 是 Least Recently Used 的缩写,即最近最少使用.作为一种经典的缓存策略,它的基本思想是长期不被使用的数据,在未来被用到的几率也不大,所以当新的数据进来时我们可以优先把这些数 ...

  6. Python中list列表的常见操作

    Python的list是一个列表,用方括号包围,不同元素间用逗号分隔. 列表的数据项不需要具有相同的类型.(列表还可以嵌套,即列表中的列表) 每个元素都有一个索引(表示位置),从0开始:可以用索引-1 ...

  7. 【前端必会】走进webpack生命周期,另类的学习方法

    背景 webpack构建过程中的hooks都有什么呢?除了在网上看一些文章,还可以通过更直接的办法,结合官方文档快速让你进入webpack的hook世界 写一个入口文件 //index.js cons ...

  8. [题解] Codeforces 468 E Permanent 折半,DP,图论

    题目 建立一个二分图,左右各n个点,在左边的第x个点和右边的第y个点之间连一条权值为\(a_{x,y}\)的边.根据"积和式"的定义,我们是要在矩阵中选择n个位置,满足任意两个位置 ...

  9. Docker | 数据持久化与数据共享

    数据持久化(安装MySQL) 参考另一篇Docker安装mysql: https://www.cnblogs.com/all-smile/p/16778376.html MySQL的数据持久化问题 # ...

  10. Java学习之路:HelloWorld

    2022-10-08 16:13:57 HelloWorld   1. 随便新建一个文件夹,存放代码   2. 新建一个Java文件 文件后缀名为.java hello.java 注意:系统没有显示后 ...