Java8的语言特性总结

虽然现在的JDK版本已经到达了11,但是jdk1.8版本的改变依然是浓墨重彩的一笔。本篇博文为自己梳理一些1.8版本的特性。由最重要的开始

关键点 1.lambda表达式 2.流以及流的实际编程使用情况

3..函数式编程 4.相关的面试题目

3.5 默认方法 3.6用Optional

博客推荐:https://blog.csdn.net/yitian_66/article/details/81010434

前言:Java8的一些概念

1.第一个编程概念是流处理:思路变成 了把这样的流变成那样的流(就像写数据库查询语句时的那种思路),而不是一次只处理一个项 目。另一个好处是,Java 8可以透明地把输入的不相关部分拿到几个CPU内核上去分别执行你的 Stream操作流水线——这是几乎免费的并行,用不着去费劲搞Thread了

2.用行为参数化把代码传递给方法 (将新的行为作为一个参数进行传递)

3.Java 8也用Stream API(java.util.stream)解决了这两个问题:集合处理时的套路和晦 涩,以及难以利用多核

1..lambda表达式:

1.概念:简洁地表示可传递的匿名函数的一种方式:它没有名称,但它 有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表

传递:可以作为参数传递给方法或者赋值给变量

简洁:无需像匿名类那样写很多模板代码

函数——我们说它是函数,是因为Lambda函数不像方法那样属于某个特定的类。但和方 法一样,Lambda有参数列表、函数主体、返回类型,还可能有可以抛出的异常列表

2.语法:

基本语法样式:

(parameters) -> expression

(parameters) -> { statements; }

1.创建对象 ()->new Apple(10)

2.比较两个对象 (Apple a1, Apple a2)->a1.getWeight.compator((a2.getWeight))

3.消费一个对象

3.函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是 可以有多个非抽象方法的接口。

用函数式接口可以干什么呢?Lambda表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例(具体说来,是函数式接口一个具体实现 的实例)

比较:Runnable r1 = () -> System.out.println("Hello World 1"); (使用Lambda )

(使用内部类)

Runnable r2 = new Runnable(){

public void run(){

System.out.println("Hello World 2");

}

};

例子:

@FunctionalInterface interface GreetingService { void sayMessage(String message); }

//那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):

GreetingService greetService1 = message -> System.out.println("Hello " + message);

3.函数式编程:

3.5流(并行流:parallelStream)(作用:高效地处理集合)

流是Java API的新成员,它允许你以声明性方式处理数据集合(通过查询语句来表达,而不 是临时编写一个实现)。就现在来说,你可以把它们看成遍历数据集的高级迭代器。此外,流还

可以透明地并行处理,你无需写任何多线程代码了

好处

声明性——更简洁,更易读

可复合——更灵活

可并行——性能更好

流的API使用

//筛选出所有素菜,创建一张素食菜单:

@Test

public void test1() {

List<Dish> sucai = menu.stream()

.filter(Dish::isVegetarian)

.collect(Collectors.toList());

sucai.forEach(a->System.out.println(a.getName()+" "));

}

区分:中间操作与终端操作

。重要的是,除非流水线上触发一个终端操作,否则中间操作不会执行任何处理——它们很懒。 这是因为中间操作一般都可以合并起来,在终端操作时一次性全部处理。

流的使用API

distinct

limit

skip(n)

map

查找和匹配

1. anyMatch方法可以回答“流中是否有一个元素能匹配给定的谓词

if(menu.stream().anyMatch(Dish::isVegetarian)){

System.out.println("The menu is (somewhat) vegetarian friendly!!");

}

anyMatch方法返回一个boolean,因此是一个终端操作

默认方法

介绍:在Java8中为interface中的接口提供了默认的实现

解决的问题是:接口与实现类之间的耦合度太高,修改接口里的抽象方法,每个实现类都必须去修改

默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现

例子如下:使用default

  1. interface InterfaceA {
  2. default void foo() {
  3. System.out.println("InterfaceA foo");
  4. }
  5. }

JDK8及以后,允许我们在接口中定义static方法和default方法。

public interface JDK8Interface {

// static修饰符定义静态方法

static void staticMethod() {

System.out.println("接口中的静态方法");

}

// default修饰符定义默认方法

default void defaultMethod() {

System.out.println("接口中的默认方法");

}

}

静态方法,只能通过接口名调用,不可以通过实现类的类名或者实现类的对象调用。default方法,只能通过接口实现类的对象来调用。

default方法也可以被实现类复写

Optional代替 null(Optional不是对null关键字的一种替代,而是对于null判定提供了一种更加优雅的实现。)

变量存在时,Optional类只是对类简单封装。变量不存在时,缺失的值会被建模成一个“空” 的Optional对象,由方法Optional.empty()返回。Optional.empty()方法是一个静态工厂 方法,它返回Optional类的特定单一实例。你可能还有疑惑,null引用和Optional.empty() 有什么本质的区别吗?从语义上,你可以把它们当作一回事儿,但是实际中它们之间的差别非常 大:如果你尝试解引用一个null,一定会触发NullPointerException,不过使用 Optional.empty()就完全没事儿,它是Optional类的一个有效对象,多种场景都能调用,非 常有用

4.Java8面试题目:

0. Java1.8引入了哪一些新特性,解决了什么问题

1.Java8支持函数编程是什么意思?

在jdk1.8之前所有东西都是面向对象的java中的 所有内容都作为对象存在。对方法/函数的所有调用都是使用对象或类引用进行的。方法/功能本身并不是独立存在的。使用Java 8,引入了函数式编程。所以我们可以使用匿名函数。Java是一种一流的面向对象语言。除了原始数据类型之外,Java中的所有内容都是一个对象。即使是一个数组也是一个对象。每个类都创建对象的实例。没有办法只定义一个独立于Java的函数/方法。无法将方法作为参数传递或返回该实例的方法体。

2.什么是Lambda表达式?

以定义为允许用户将方法作为参数传递的匿名函数。这有助于删除大量的样板代码。Lambda函数没有访问修饰符(私有,公共或受保护),没有返回类型声明和没有名称。

Lambda表达式允许用户将“函数”传递给代码。所以,与以前需要一整套的接口/抽象类想必,我们可以更容易地编写代码。例如,假设我们的代码具有一些复杂的循环/条件逻辑或工作流程。使用lambda表达式,在那些有难度的地方,可以得到很好的解决。

3.lambda表达式的优点是什么?

  • 通过Java 8,可以更轻松地在多个线程上分发集合的处理。 集合现在可以在内部组织自己的迭代,将并行化的责任从客户端代码转移到库代码中。
  • 更少的代码行。
  • 使用Java 8 Lambda表达式可以实现更高的效率。通过使用具有多核的CPU,用户可以通过使用lambda并行处理集合来利用多核CPU。

4.Java8你了解吗

1、 HashMap 的底层实现有变化:

HashMap 是数组 + 链表 + 红黑树(JDK1.8 增加了红黑树部分)实现。

2.在接口定义中可以使用默认方法

3、Lambda 表达式(也称为闭包),允许我们将函数当成参数传递给某个方法,或者把代码本身当做数据处理。使用Lambda 表达式可以使代码变的更加简洁紧凑。

4、 函数式接口:

指的是只有一个函数的接口,java.lang.Runnable 和 java.util.concurrent.Callable 就是函数式接口的例子;java8 提供了一个特殊的注解 @Functionallnterface 来标明该接口是一个函数式接口。

5.Optional来优化null

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常

6.提供了Stream API来高效地处理集合

可以让你以一种声明的方式处理数据。

Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。

Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

思路:为什么需要lambda表达式:(传递行为化参数)

demo:按照条件过滤集合

不优化原始方法:每次都是for循环按照条件过滤

优化方式一:按照策略模式进行优化,将行为条件实现特定的接口方法进行传参

缺点:麻烦,每次一个新的策略都要重新写一个类

优化方式二:在优化方式一的情况之下使用匿名内部类

相比优化方式一:显得便捷一点

缺点:主要的代码就是一句,所以还是挺麻烦的。

优化方式三:lambda表达式

贴图

lambda基础语法:

左侧是函数式借口的参数,右侧是方法体

语法一:无参数,无返回值

( ) -> System.out.println("hello");

Runnable runnable = () ->System.out.println("hello");

语法二:有参数,无返回

Consumer<String> consumer = (m)->System.out.println(m);

consumer.accept("你哈");

对consumer的accept()抽象方法进行实现

注意:左侧只有一个参数,()可以忽略

语法三:两个以上参数,有返回值,方法体有多条语句

要使用大括号哦

Comparator<Integer> comparator = (x,y) ->{

System.out.println("多条语句实现");

return Integer.compare(x, y);

};

comparator.compare(4, 74);

语法格式六:lambda表达式的参数类型可以不写,因为JVM的编译器通过上下文进行推断

二、lambada表达式需要函数式接口的支持

@FunctionalInterface

interface ILambdaCaculator{

int result(int a,int b);

}

public class LambdaTest {

public static void main(String[] args) {

System.out.println("add :"+LambdaUse((a,b)-> a+b,12,14));

}

//将lambada表达式作为行为化参数传入方法中

public static int LambdaUse(ILambdaCaculator lambda,int a,int b){

return lambda.result(a, b);

}

}

Java8内置的四大核心函数式接口

1.Consumer<T> :消费型接口

void accept(T t)

2.Function<T,R>:函数型

R apply(T, t)

3.Predicate<T>:断言接口

boolean test(T t)

4.Supplier<T>:供给接口

T get()

四大接口类型的Demo

public class TestLambda2 {

// 消费性接口(无返回值)

public void happy(double money, Consumer<Double> con) {

con.accept(money);

}

@Test

public void test1() {

happy(1111, (m) -> System.out.println("消费了" + m));

}

//////////////////////////////////////////

// 供给型接口

// 需求:产生特定的整数,并放入集合中

public List<Integer> getNumberList(int num, Supplier<Integer> sup) {

List<Integer> list = new ArrayList<Integer>();

for (int i = 0; i < num; i++) {

list.add(sup.get());

}

return list;

}

@Test

public void test2() {

List<Integer> list = getNumberList(100, () -> (int) (Math.random() * 100));

for (Integer num : list) {

System.out.println(num);

}

}

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

public String stringHandler(String str, Function<String, String> fun) {

return fun.apply(str);

}

@Test

public void test3() {

String aString = stringHandler("hasfasfad", str -> str.toUpperCase());

System.out.println("转化为大写:" + aString);

}

}

//需求:将满足条件的字符串放入集合中

public List<String> filterStrings (List<String> list, Predicate<String> pre){

List<String> strList = new ArrayList<String>();

for(String str :list){

if(pre.test(str)){

strList.add(str);

}

}

return strList;

}

@Test

public void test4(){

List<String> list = new ArrayList<String>();

list.add("hesdsfd");

list.add("sfsdf");

list.add("s");

List<String> list2 = filterStrings(list, (str) ->str.length() >3);

for(String str:list2){

System.out.println(str);

}

}

}

方法引用:如果lambda表达式中的内容有方法已经实现了,我们就可以使用方法引用

主要的语法形式:

对象::实例方法名

类::静态方法名

类::实例方法名

   

发布了29 篇原创文章 · 获赞 34 · 访问量 8151

猜你喜欢

转载自blog.csdn.net/weixin_39634532/article/details/94745522