LIST函数JAVA特点_Java8新特性实在太好用了!!

前言

面试的时候被问到了Java8新特性,忘记了很多,好好整理了关于Java8新特性的知识,如果有写得不对的地方还请大佬指正,让我们畅游在知识的海洋中吧

1450a5c1733e5df6ff2e7f777078fe9d.png

1. Lambda表达式

Lambda 表达式是一种匿名函数(对 Java 而言这并不完全正确,但现在姑且这么认为),简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。

我们总是通过匿名类给方法传递函数功能,以下是旧版的事件监听代码:

someObject.addMouseListener(new MouseAdapter() {

public void mouseClicked(MouseEvent e) {

//Event listener implementation goes here...

}

});

在上面的例子里,为了给 Mouse 监听器添加自定义代码,我们定义了一个匿名内部类 MouseAdapter 并创建了它的对象,通过这种方式,我们将一些函数功能传给 addMouseListener 方法。

在 Java 里将普通的方法或函数像参数一样传值并不简单,为此,Java 8 增加了一个语言级的新特性,名为 Lambda 表达式。

1.1 函数式接口

要注意的是想使用Lambda表达式就必须使用函数式接口,如果使用函数式接口,那么该接口之中就只能有一个抽象方法

Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现.

举例:

package com.yztcedu.lambdademo_01;

@FunctionalInterface //添加此注解后,接口中只能有一个抽象方法。

public interface A {

void call();

}

1.2 lambda语法

包含三部分:

1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数

2、一个箭头符号:->

3、方法体,可以是表达式和代码块

(parameters) -> expression 或者 (parameters) -> { statements; }

Runnable runnable = () -> System.out.println("这个是用拉姆达实现的线程");

如果不使用Lambda表达式情况是这样的:

Runnable runnable = new Runnable() {

@Override

public void run() {

System.out.println("这个是用内部类实现的线程");

}

};

1.3 方法引用

其实是lambda表达式的一种简化写法。所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。如下所示:

如果是静态方法,则是ClassName::methodName。如 Object ::equals

如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;

构造函数.则是ClassName::new

Runnable runnable = Demo2::run;

public static void run(){

System.out.println("方法引用的代码...");

}

1.4 默认方法---接口改进

简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。

package com.yztcedu.lambdademo_01;

@FunctionalInterface

public interface A {

void call();

default void fun() {

System.out.println("我是接口的默认方法1中的代码");

}

default void fun2() {

System.out.println("我是接口的默认方法2中的代码");

}

}

为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类

2. Stream 数据流

在JAVA8之前的传统编程方式,如果我们需要操作一个集合数据,需要使用集合提供的API,通过一个循环去获取集合的元素,这种访问数据的方式会使代码显得臃肿,JAVA8新引入的Stream类,用于重新封装集合数据,通过使用流式Stream代替常用集合数组、list和map的遍历操作可以极大的提高效率

可以形象地理解Stream的操作是对一组粗糙的工艺品原型(即对应的 Stream 数据源)进行加工成颜色统一的工艺品(即最终得到的结果),第一步筛选出合适的原型(即对应Stream的 filter 的方法),第二步将这些筛选出来的原型工艺品上色(对应Stream的map方法),第三步取下这些上好色的工艺品(即对应Stream的 collect(toList())方法)。在取下工艺品之前进行的操作都是中间操作,可以有多个或者0个中间操作,但每个Stream数据源只能有一次终止操作,否则程序会报错。

实际项目操作代码:

class Employee {

private Long empno; //员工号

private String ename; //员工姓名

private Integer salary; //薪水

private Integer deptno; //所属部门号

//此处省略get/set方法、构造方法以及toString方法

}

Employee e1 = new Employee(7369L, "SMITH", 800, 20);

Employee e2 = new Employee(7499L, "ALLEN", 1600, 30);

Employee e3 = new Employee(7521L, "WARD", 1250, 30);

Employee e4 = new Employee(7782L, "CLARK", 2450, 10);

Employee e5 = new Employee(7876L, "ADAMS", 1100, 20);

List employees = Arrays.asList(e1, e2, e3, e4, e5);

forEach方法

forEach方法用于迭代stream流中的每一个元素

employees.stream().forEach(System.out::println);

执行结果:

Employee{empno=7369, ename='SMITH', salary=800, deptno=20}

Employee{empno=7499, ename='ALLEN', salary=1600, deptno=30}

Employee{empno=7521, ename='WARD', salary=1250, deptno=30}

Employee{empno=7782, ename='CLARK', salary=2450, deptno=10}

Employee{empno=7876, ename='ADAMS', salary=1100, deptno=20}

map方法

//map方法用于根据自定义的规则对stream流中的数据做一对一的映射

//获取所有员工的姓名

List enames = employees.stream().map(employee -> employee.getEname()).collect(Collectors.toList());

enames.stream().forEach(System.out::println);

执行结果:

SMITH

ALLEN

WARD

CLARK

ADAMS

从Java 8开始,使用ArrayList的新API加上lambda表达式,我们可以这样写:

list.forEach(e -> System.out.println(e));

而这里的lambda表达式的内容其实只不过就是把参数传给了println()方法,而没有做任何别的事情,所以可以进一步简写为:

list.forEach(System.out::println);

仅此而已。

System.out是一个PrintStream实例的引用;System.out::println 是对一个实例方法的引用

该引用同时指定了对实例(System.out)的引用以及对方法(PrintStream::println)的引用

System.out::println 不是 System.out.println 的等价物;前者是一个方法引用表达式,而后者不能单独作为一个表达式,而必须在后面跟上由圆括号包围的参数列表来构成方法调用表达式。

System.out::println 可以看作 lambda表达式 e -> System.out.println(e) 的缩写形式。

常用的stream流操作

28ce9a89e7a32b1bfcfa4b3d5bbf9b39.png

1.collect(toList()) 终止操作

由Stream中的值生成一个List列表,也可用collect(toSet())生成一个Set集合。

例:取 Stream 中每个字符串并放入一个新的列表

@Test

public void collectToList() {

String[] testStrings = { "java", "react", "angular", "vue" };

List list = Stream.of(testStrings).collect(Collectors.toList());

for (int i = 0, length = list.size(); i < length; i++) {

System.out.println(list.get(i));

}

}

5294794521d70b826cb00e922d099425.png

2.map 中间操作

将一种类型的值映射为另一种类型的值,可以将 Stream 中的每个值都映射为一个新的值,最终转换为一个新的 Stream 流。

例:把 Stream 中每个字符串都转换为大写的形式,

@Test

public void mapTest() {

String[] testStrings = { "java", "react", "angular", "vue" };

List list = Stream.of(testStrings).map(test -> test.toUpperCase()).collect(Collectors.toList());

list.forEach(test -> System.out.println(test));

}

3.filter 中间操作

遍历并筛选出满足条件的元素形成一个新的 Stream 流。

例:筛选出以 j 字母开头的元素个数,此例中的count方法也是终止操作,是为了计算出 Stream 中的元素个数

@Test

public void filterTest() {

List list = Arrays.asList("java", "react", "angular", "javascript", "vue");

long count = list.stream().filter(p -> p.startsWith("j")).count();

System.out.println(count);

}

还有很多方法就不多列举了 喜欢的可以自行查找哦

5e9623088ffaeac6b1256ee65e09fde8.png

创作不易,如果本篇文章能帮助到你,请给予支持,赠人玫瑰,手有余香,虫虫蟹蟹观众姥爷了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值