前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 8 新特性 | 总结

Java 8 新特性 | 总结

作者头像
Java小技巧
发布2022-10-27 10:41:32
2260
发布2022-10-27 10:41:32
举报
文章被收录于专栏:Java小技巧Java小技巧

一、Lambda表达式

1、函数式接口

如果说,一个接口中,要求实现类必须实现的抽象方法,有且只有一个!这样的接口就是函数式接口*注:接口里的方法有default修饰(有方法体),子类可以重写也可以不重写

代码语言:javascript
复制
//非函数式接口,Object类中有默认的toString方法,可以不重写
interface Test{
   String toString();
}

2、@FunctionalInterface注解

用在接口之前,判断这个接口是否是一个函数式接口。如果是函数式接口,没有任何问题。如果不是函数式接口,则会报错。

代码语言:javascript
复制
@FunctionalInterface
interface FunctionalInterfaceTest{
    void test();
}

3、基础语法

代码语言:javascript
复制
(参数类型 参数,参数类型 参数)->{
  方法体
};

4、语法进阶

(1)参数的类型可以不写,在接口方法中已经定义过。

(2)如果需要省略参数的类型,要保证:要省略,每一个参数的类型都必须省略不写。绝对不能出现,有的参数类型省略了,有的参数类型没省略

代码语言:javascript
复制
//多个参数、无返回值的方法实现
NoneReturnMutipleParameter lambda1=(a,b)->{
    System.out.println("多个参数、无返回值方法的实现:参数a是"+a+", 参数b是"+b);
}

(3)如果参数列表中的参数数量有且只有一个,此时,参数列表的小括号是可以省略不写的,省略小括号的同时必须省略参数的类型

代码语言:javascript
复制
//有参、无返回值的方法实现
NoneReturnSingleParameter lambda2=a->{
    System.out.println("一个参数、无返回值方法的实现:参数是 " + a);
}

(4)当一个方法体中的逻辑,有且只有一句的情况下,大括号可以省略

代码语言:javascript
复制
//有参、无返回值的方法实现
NoneReturnSingleParameter lambda2=a->System.out.println("一个参数、无返回值方法的实现:参数是 " + a);

(5)如果一个方法中唯一的一条语句是一个返回语句,此时在省略大括号的同时,也必须省略return

代码语言:javascript
复制
SingleReturnMultipleParameter lambda3=(a,b)->a+b;

5、函数引用:引用一个已经存在的方法,使其替代lambda表达式完成接口的实现

(1)静态方法的引用

  • 语法 类::静态方法
  • 注意事项:引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致
代码语言:javascript
复制
public class Syntax1 {
    public static interface Calculate{
        int calculate(int a,int b);
    }

    //静态方法的引用
    public static void main(String[] args){
        //实现一个多个参数的、一个返回值的接口
        //对一个静态方法的引用
        Calculate lambda1=Syntax1::calculate;
        System.out.println(lambda1.calculate(,));
    }

    private static int calculate(int x,int y){
        if(x>y){
            return x-y;
        }else if(x<y){
            return y-x;
        }
        return x+y;
    }
}

(2)非静态方法的引用

  • 语法 对象::非静态方法
  • 引用的这个方法,参数(数量、类型)和返回值,必须要跟接口中定义的一致
代码语言:javascript
复制
public class Syntax1 {
    public static interface Calculate{
        int calculate(int a,int b);
    }

    //静态方法的引用
    public static void main(String[] args){
        //实现一个多个参数的、一个返回值的接口
        //对一个静态方法的引用
        Calculate lambda1=Syntax1::calculate;
        System.out.println(lambda1.calculate(,));
        //对一个非静态方法的引用
        Calculate lambda2=new Syntax1()::calculate2;
        System.out.println(lambda2.calculate(,));
    }

    private int calculate2(int a,int b){
        if(a!=b){
            return a-b;
        }else{
            return a+b;
        }
    }

    private static int calculate(int x,int y){
        if(x>y){
            return x-y;
        }else if(x<y){
            return y-x;
        }
        return x+y;
    }
}

(3)构造方法的引用

  • 语法 类名::new
  • 可以通过接口中的方法的参数,区分引用不同的构造方法
代码语言:javascript
复制
public class Lambda2 {
    public static class Person{
        String name;
        int age;
        public Person(){
            System.out.println("Person类的无参构造方法执行了");
        }
        public Person(String name){
            this.name=name;
            System.out.println("Person类的有参数构造方法执行了");
        }
        public Person(String name,int age){
            this.name=name;
            this.age=age;
            System.out.println("Person类的两个参数构造方法执行了");
        }
    }

    private interface GetPersonWithNoneParameter{
        Person get();
    }

    private interface GetPersonWithSingleParameter{
        Person get(String name);
    }

    private interface GetPersonWithMultipleParameter{
        Person get(String name,int age );
    }

    public static void main(String[] args){
        GetPersonWithNoneParameter getPerson=Person::new;
        getPerson.get();
        GetPersonWithSingleParameter getPerson1=Person::new;
        getPerson1.get("张三");
        GetPersonWithMultipleParameter getPerson2=Person::new;
        getPerson2.get("张三",);
    }
}

(4)对象的特殊用法

  • 如果lambda表达式中包含了某一个对象,此时方法体中,直接使用这个对象调用它的某一个方法就可以完成整体的逻辑。其他的参数可以作为调用方法的参数。此时可以简化为 类::方法,方法不加括号
代码语言:javascript
复制
public class Lambda3 {
    public static class Person{
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public interface MyInterface{
        //String get(Person person);
        void set(Person person,String name);
    }

    public static void main(String[] args){
        Person xiaoming=new Person();
        xiaoming.setName("xiaoming");

//        MyInterface lambda1=x->x.getName();
//        MyInterface lambda2=Person::getName;
//        System.out.println(lambda2.get(xiaoming));

        MyInterface lambda3=(x,n)->x.setName(n);
        MyInterface lambda4=Person::setName;
        lambda4.set(xiaoming,"123");
        System.out.println(xiaoming.getName());

    }
}

(5)lambda表达式注意事项

代码语言:javascript
复制
public class Lambda5 {
    private static int y=;
    public static void main(String[] args){
        //1.定义一个局部变量
        int x=;
        //2.使用lambda表达式实现接口
        LambdaTest lambda=()->{
            System.out.println("x="+x);
            System.out.println("y="+y);
        };
        //3.修改变量x的值(此处是局部变量,不能更改值,不注销)
        //x=20;
        //4.修改变量y的值
        y=;
    }
}

二、集合的流式编程

  • 简介:把数据源中的数据读到Stream流里面,对Stream流里面的数据进行操作(删除、过滤、映射等),每次操作结果也是一个流对象,可以对这个流再进行其他的操作,最后将Stream流里的数据放到集合或者数组里。
  • 流式编程的步骤

(1)获取数据源,将数据源中的数据读取到流中

(2)对流中的数据进行各种各样的处理

(3)对流中的数据进行整合处理

其中(2)称为中间操作,(3)称为最终操作。

1、数据源的获取

(1)数据源的简介

*注意:将数据读取到流中进行处理的时候,与数据源中的数据没有关系。也就是说,中间操作对流的数据进行处理、过滤、映射、排序等,此时是不会影响数据源中的数据的

(2)数据源的获取

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 集合流式编程中的数据源的读取
 * 读取数据源中的数据,得到一个流对象
 */
public class DataSource {
    public static void main(String[] args){
        collectionDataSource();
        arrayDataSource2();
    }

    /**
     * 将list作为数据源,读取list中的数据到一个流中
     */
    public static void collectionDataSource(){
        //1.实例化一个集合
        List<Integer> list=new ArrayList<>();
        //2.填充元素
        Collections.addAll(list,,,,,,,,,,);
        //3.读取集合中的数据,将其读取到流中
        Stream<Integer> stream=list.stream();
        //4.输出stream
        System.out.println(stream);
    }

    public static void arrayDataSource(){
        //1.实例化一个数组
        Integer[] array=new Integer[]{,,,,,,,,,};
        //2.读取数组中的数据到流中,得到一个流对象
        Stream<Integer> stream= Arrays.stream(array);
        //3.输出stream
        System.out.println(stream);
    }

    public static void arrayDataSource2(){
        //1.实例化一个数组
        int[] array=new int[]{,,,,,,,,,};
        //2.读取数组中的数据到流中,得到一个流对象
        IntStream stream= Arrays.stream(array);
        //3.输出stream
        System.out.println(stream);
    }
}

2、最终操作

(1)将流中的数据收集到一起,对这些数据进行一些处理,最常见的处理,就是将流中的数据存入一个集合。

*注意:最终操作,之所以叫最终操作,是因为,在最终操作执行结束后,会关闭这个流,流中的所有数据都会销毁。如果使用一个已经关闭了的流,会出现异常。

(2)collect:将流中的元素放到集合里

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 最终操作
 */
public class FinalOperation {
    public static void main(String[] args){
        collectUsage();
    }
    /**
     * 最终操作:collect
     */
    public static void collectUsage(){
        //1.获取数据源
        Stream<Integer> dataSource=getDataSource();
        //2.流中的数据的聚合
        //List<Integer> list=dataSource.collect(Collectors.toList());
        Map<String,Integer> list=dataSource.collect(Collectors.toMap(i->i.toString(), i->i));
        System.out.println(list);
    }
    /**
     * 数据源的获取,从一个容器中获取数据源中的数据
     * @return读取数据源中的数据,得到一个Stream对象
     */
    public static Stream<Integer> getDataSource(){
        //1.准备一个容器
        List<Integer> dataSource=new ArrayList<>();
        //2.向数据源中添加数据
        Collections.addAll(dataSource,,,,,,,,,,);
        //3.读取数据源中的数据,得到Stream对象并返回
        return dataSource.stream();
    }
}

(3)reduce:将流中的数据按照一定的规则聚合起来

代码语言:javascript
复制
//将流的元素,逐一带入到这个方法中,进行运算
//最终的运算结果,得到的其实是一个Optional类型,需要使用get()获取到里面的数据
int result=list.stream().reduce((e1,e2)->e1+e2).get();
System.out.println(result);

(4)count:统计流中元素的数量

代码语言:javascript
复制
long result=list.stream().count();
System.out.println(result);

(5)forEach:迭代、遍历流中的数据

代码语言:javascript
复制
list.stream().forEach(System.out::println)

(6)max&&min

代码语言:javascript
复制
list.stream().min(Integer::compareTo).get();

(7)Matching

  • allMatch:只有当流中所有元素,都匹配指定的规则,才会返回true
  • anyMatch:只要流中有任意的数据,满足指定的规则,都会返回true
  • noneMatch:只有当流中的所有的元素,都不满足指定的规则,才会返回true
代码语言:javascript
复制
//判断流中是否所有的元素都大于50
boolean result=list.stream().allMatch(ele->ele > );
//判断流中是否有大于50的数据
boolean result=list.stream().anyMatch(ele->ele > );
//判断流中是否都是偶数
boolean result=list.stream().noneMatch(ele->ele%!=);

(8)find

  • findFirst:从流中获取一个元素(获取的是开头的元素)
  • findAny:从流中获取一个元素(一般情况下,是获取的开头的元素) 这两个方法,绝大部分情况下,是完全相同的,但是在多线程的环境下,这两个返回的结果可能不一样。
代码语言:javascript
复制
Integer integer=list.stream().findFirst().get();
Integer integer=list.stream().findAny().get();

(9)IntStream的使用

代码语言:javascript
复制
int[] array=new int[]{,,,,,,,,,};
IntStream stream=Arrays.stream(array);
System.out.println(stream.max().getAsInt());
System.out.println(stream.min().getAsInt());
System.out.println(stream.sum());
System.out.println(stream.count());
System.out.println(stream.average().getAsDouble());
//获取到一个对流中的数据的分析结果
IntSummaryStatistics intSummaryStatistics=stream.summaryStatistics();
System.out.println("max = "+intSummaryStatistics.getMax());
System.out.println("min = "+intSummaryStatistics.getMin());
System.out.println("sum = "+intSummaryStatistics.getSum());
System.out.println("average = "+intSummaryStatistics.getAverage());
System.out.println("count = "+intSummaryStatistics.getCount());

3、中间操作:将数据从数据源中读取到流中,中间操作就是对流中的数据进行各种各样的操作、处理。中间操作可以连续操作,每一个操作的返回值都是一个Stream对象,可以继续进行其他的操作,直到最终操作。

(1)filter:条件过滤,仅保留流中满足指定条件的数据,其他不满足的数据都会被删除

(2)distinct:去除流中重复的数据,需要重写对象的hashCode和equals方法

(3)limit&&skip:limit表示截取流中指定数量的数据,skip表示跳过指定数量的数据,截取剩余的部分

(4)map:对流中的数据进行映射,用新的数据替换旧的数据

代码语言:javascript
复制
list.stream().map(ele->ele+".txt").forEach(System.out::println);
IntSummaryStatistics intSummaryStatistics=dataSource.mapToInt(Student::getScore).summaryStatistics();

4、Collectors工具类

Collectors 类提供了大量方法用于指示如何收集元素。

比如 Collectors.toList() 方法可以将流中的元素收集起来,并转换为列表

代码语言:javascript
复制
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);

比如 Collectors.joining() 方法可以将流中的元素收集起来,并使用指定的字符串拼接符拼接成一个字符串。

代码语言:javascript
复制
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java小技巧 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档