JAVA8新特性及stream流

声明

本文主要是对JAVA8新特性的理解文章,如果有什么需要改进的地方还请大佬指出💐在这里插入图片描述

🥦作者简介:大家好,我是青衿😉
🍄博客首页:CSDN主页石马农青衿
🌸每日一句:努力一点,优秀一点

一、接口中的默认方法与静态方法

Java8之前的接口中只能定义全局常量,抽象方法
Java8之后的接口中能定义全局常量,抽象方法,默认方法以及静态方法

请看下面示例代码:

public interface Vehicle {

    //默认方法
   default void print(){
      System.out.println("我是一辆车!");
   }
    // 静态方法
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}

二、Lambda 表达式

Lambda 表达式本质上是一段匿名内部类,也可以是一段可以传递的代码

 new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("Thread is running before Java8!");
            }
        }).start();

这是通过内部类的方式来重写run方法,使用Lambda表达式,还可以更加简洁:

new Thread( () -> System.out.println("Thread is running since Java8!") ).start();

三、函数式接口 Functional Interface

函数接口指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式。
Java 8 提供了一个特殊的注解@FunctionalInterface,举个简单的函数式接口的定义

@FunctionalInterface
public interface GreetingService {

    void sayMessage(String message);
}

Java7 只能通过匿名内部类进行编程,例如:

GreetingService greetService = new GreetingService() {

    @Override
    public void sayMessage(String message) {
        System.out.println("Hello " + message);
    }
};
greetService.sayMessage("world");

Java8 可以采用 Lambda 表达方进行编程:

GreetingService greetService = message -> System.out.println("Hello " + message);
greetService.sayMessage("world");

四、Stream 流

Stream 流简单来说,我们可以使用 java.util.Stream 对一个包含一个或多个元素的集合做各种操作。这些操作可能是 中间操作 亦或是 终端操作。 终端操作会返回一个结果,而中间操作会返回一个 Stream 流。
1- 创建 Stream

一个数据源(如:集合、数组),获取一个流

2- 中间操作

一个中间操作链,对数据源的数据进行处理

3- 终止操作(终端操作)

一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用

在这里插入图片描述

1.Filter 过滤

filter方法用于通过设置的条件过滤出元素。
首先,我们创建一个 List 集合:

public class FilterStreamDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("周杰伦");
        list.add("王力宏");
        list.add("陶喆");
        list.add("林俊杰");
        Stream<String> stream = list.stream().filter(element -> element.contains("王"));
        stream.forEach(System.out::println);
    }
}

element -> element.contains(“王”) 就是筛选出带有“王”的字符串。
forEach() 方法接收的是一个 Consumer(Java 8 新增的一个函数式接口,接受一个输入参数并且无返回的操作)类型的参数,类名 :: 方法名是 Java 8 引入的新语法,System.out 返回 PrintStream 类,println 方法你应该知道是打印的。forEach方法用于迭代流中的每个数据,类似于下面的代码

for (String s : strs) {
    System.out.println(s);
}

**注:**foreach 是一个终端操作,它的返参是 void, 我们无法对其再次进行流操作。

2.Sorted 排序

Sorted 同样是一个中间操作,它的返参是一个 Stream 流。另外,我们可以传入一个 Comparator 用来自定义排序,如果不传,则使用默认的排序规则。


public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(5, 2, 1, 4, 3);
        
        // 使用stream的sorted方法进行排序
        List<Integer> sortedNumbers = numbers.stream()
            .sorted()
            .collect(Collectors.toList());
        
        System.out.println(sortedNumbers);
    }
}

当你运行这段代码时,它会输出排序后的整数列表:

[1, 2, 3, 4, 5]

3.Map 转换

如果想通过某种操作把一个流中的元素转化成新的流中的元素,可以使用 map() 方法。
中间操作 Map 能够帮助我们将 List 中的每一个元素做功能处理。例如下面的示例,将英文字符串数组的元素全部改为大写。整数数组每个元素+3

public class StreamTest {
	public static void main(String[] args) {
		String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
		List<String> strList = Arrays.stream(strArr).map(String::toUpperCase).collect(Collectors.toList());

		List<Integer> intList = Arrays.asList(1, 3, 5, 7, 9, 11);
		List<Integer> intListNew = intList.stream().map(x -> x + 3).collect(Collectors.toList());

		System.out.println("每个元素大写:" + strList);
		System.out.println("每个元素+3:" + intListNew);
	}
}

把 Stream 的流转成一个 Stream 的流。
程序输出的结果如下所示:

3
3
2
3

4.Collectors

Collectors类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors可用于返回列表或字符串:

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

        // 使用stream的map方法将每个整数转换为其字符串表示,然后收集到一个集合中
        Set<String> numberSet = numbers.stream()
            .map(String::valueOf)
            .collect(Collectors.toSet());

        System.out.println(numberSet);
    }
}

当你运行这段代码时,它会输出收集后的集合:

[1, 2, 3, 4, 5]

注意,因为我们使用了map方法将每个整数转换为其字符串表示,所以集合中的元素是字符串,而不是整数。这就是Java Stream的map和Collectors.toSet方法的组合使用,它可以用来将Stream中的元素转换并收集到一个Set中。

5.Count 计数

count 是一个终端操作,它能够统计 stream 流中的元素总数,返回值是 long 类型。

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> words = Arrays.asList("Hello", "World", "I", "am", "AI");

        // 使用stream的count方法计算元素数量
        long count = words.stream()
            .count();

        System.out.println(count);
    }
}

它可以用来计算Stream中的元素数量。

五、Optional 类

Optional是用于防范NullPointerException。
可以将 Optional 看做是包装对象(可能是 null, 也有可能非 null)的容器。当我们定义了 一个方法,这个方法返回的对象可能是空,也有可能非空的时候,我们就可以考虑用 Optional 来包装它,这也是在 Java 8 被推荐使用的做法。

public class OptionalTester {

    public static void main(String[] args) {
        OptionalTester tester = new OptionalTester();
        Integer value1 = null;
        Integer value2 = new Integer(10);

        // Optional.ofNullable - 允许传递为 null 参数
        Optional<Integer> a = Optional.ofNullable(value1);

        // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
        Optional<Integer> b = Optional.of(value2);
        System.out.println(tester.sum(a,b));
    }

    public Integer sum(Optional<Integer> a, Optional<Integer> b){

        // Optional.isPresent - 判断值是否存在

        System.out.println("第一个参数值存在: " + a.isPresent());
        System.out.println("第二个参数值存在: " + b.isPresent());

        // Optional.orElse - 如果值存在,返回它,否则返回默认值
        Integer value1 = a.orElse(new Integer(0));

        //Optional.get - 获取值,值需要存在
        Integer value2 = b.get();
        return value1 + value2;
    }
}

文章到此就结束了,感谢各位小伙伴儿们的支持,点个关注把💐
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值