侧边栏壁纸
博主头像
快乐江湖的博客博主等级

更多内容请点击CSDN关注“快乐江湖”

  • 累计撰写 127 篇文章
  • 累计创建 33 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

第十七章:Java之lambda表达式

快乐江湖
2023-04-24 / 0 评论 / 0 点赞 / 14 阅读 / 17501 字

专栏目录首页:【专栏必读】Java基础教程和数据结构内容导航和学习说明

一:lambda表达式相关概念

(1)lambda表达式定义

lambda表达式:lambda表达式是Java SE8中引入的一个新特性。它允许你通过表达式代替功能接口。它和普通方法一样,提供了一个正常的参数列表和一个使用这些参数的主体。lambda表达式本质是一个匿名内部类(更进一步其实是匿名内部类的简化),也就是说lambda表达式实际上是创建了一个类、实现了接口然后重写了接口的方法

  • 有关匿名内部类详见这篇文章:链接

(2)函数式接口

函数式接口:函数式接口是指一个接口有且只有一个抽象方法。在Java中,如果我们在某个接口上声明了@FunctioanlInterface注解,那么编译器就会按照函数式接口的定义来要求改接口必须只有一个抽象方法

@FunctionalInterface
public interface A {
    void test();
}

(3)lambda表达式语法

lambda表达式语法:其基本语法为(parameters)->expression(parameters)->{statements;},这三部分内容含义如下

  • (paramaters):类似方法中的形参列表,这里的参数是函数式接口里的参数,其参数类型可以明确声明也可以交由JVM判断(只有一个判断类型时可以省略圆括号)
  • ->:可以理解为“被用于”的意思
  • expression{statements;}:类似于方法里的实现可以返回一个值也可以什么都不用返回

下面是一些例子,可以帮助大家理解

  • ()->2:不需要参数,返回值为2
  • x->2*x:接受一个参数(数字),返回其2倍的值
  • (x, y):接受两个参数(均为数字),返回它们的和
  • (int x, int y)->x*y:接受两个整型,返回它们的乘积
  • (String s) -> System.out.print(s):接受一个String对象,并在控制台打印,不返回任何值

二:lambda表达式的基本使用

在使用前,我们先准备好以下接口,它们代表了各种类型的函数式接口

//无返回值无参数
@FunctionalInterface
interface NoParameterNoReturn{
    void test();
}

//无返回值一个参数
@FunctionalInterface
interface OneParameterNoReturn{
    void test(int a);
}


//无返回值多个参数
@FunctionalInterface
interface MoreParametersNoReturn{
    void test(int a, int b);
}


//有返回值无参数
@FunctionalInterface
interface NoParameterReturn{
    int test();
}

//有返回值一个参数
@FunctionalInterface
interface OneParameterReturn{
    int test(int a);
}


//有返回值多个参数
@FunctionalInterface
interface MoreParameterReturn{
    int test(int a, int b);
}

在不使用lambda的情况下,调用它们时可以采用匿名内部类的方式

public class TestDemo {
    public static void main(String[] args) {
        NoParameterNoReturn noParameterNoReturn = new NoParameterNoReturn() {
            @Override
            public void test() {
                System.out.println("无参数无返回值");
            }
        };
        noParameterNoReturn.test();
    }
}

具体实例如下,以下代码中部分语句可再次精简(但不推荐这样做),规则如下

  • 参数类型可以省略,如果需要省略,则每个参数类型都要省略
  • 如果参数的小括号内只有一个参数,那么小括号可以省略
  • 如果方法体当中只有一句代码,那么大括号可以省略
public class TestDemo {
    public static void main(String[] args) {
        //无返回值无参数
        NoParameterNoReturn noParameterNoReturn = ()->{
            System.out.println("无返回值无参数1次");
            System.out.println("无返回值无参数2次");
        };
        noParameterNoReturn.test();
        System.out.println("=======================================================");

        //无返回值一个参数
        OneParameterNoReturn oneParameterNoReturn = (int a) ->{
            System.out.println("无返回值一个参数1次,传入参数为:" + a);
            System.out.println("无返回值一个参数2次,传入参数为:" + a);

        };
        oneParameterNoReturn.test(100);
        System.out.println("=======================================================");

        //无返回值多个参数
        MoreParametersNoReturn moreParametersNoReturn = (int a, int b) ->{
            System.out.println("无返回值多个参数1次,传入参数为:" + a + "和" + b);
            System.out.println("无返回值多个参数2次,传入参数为:" + a + "和" + b);
        };
        moreParametersNoReturn.test(200, 300);
        System.out.println("=======================================================");

        //有返回值无参数
        NoParameterReturn noParameterReturn = ()->{
            return 10;
        };
        int ret1 = noParameterReturn.test();
        System.out.println("返回值为:" + ret1);
        System.out.println("=======================================================");

        //有返回值一个参数
        OneParameterReturn oneParameterReturn = (int a)->{
            return a*a;
        };
        int ret2 = oneParameterReturn.test(10);
        System.out.println("参数:" + 10 + ";返回值为:" + ret2);
        System.out.println("=======================================================");

        //有返回值多个参数
        MoreParameterReturn moreParameterReturn = (int a, int b)->{
          return a * b;
        };
        int ret3 = moreParameterReturn.test(8, 9);
        System.out.println("参数a:" + 8 + ";参数b:" + 9 + ";返回值为:" + ret3);
        System.out.println("=======================================================");
    }
}

三:lambda在集合中的使用

为了能够让lambda和Java中集合类更好的配合使用,在集合当中新增了部分接口,见下表

对应接口新增方法
CollectionremoveIf() spliterator() stream() parallelStream() forEach()
ListreplaceAll() sort()
MapgetOrDefault() forEach() replaceAll() putIfAbsent() remove() replace() computeIfAbsent() computeIfPresent() compute() merge()

下面做部分演示

(1)Collection接口

forEach()方法:对容器中的每个元素执行accept指定的动作

public class TestDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("三国演义");
        list.add("水浒传");
        list.add("红楼梦");
        list.add("西游记");

        //匿名内部类实现
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s);
            }
        });
        System.out.println();
        //lambda实现
        list.forEach((String s) -> {
            System.out.print(s);
        });
        System.out.println();
    }
}

(2)List接口

sort()方法:该方法根据c指定的比较规则对容器元素进行排序

public class TestDemo {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("what");
        list.add("are");
        list.add("you");
        list.add("dong");
        list.add("now");

        //匿名内部类实现
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        list.forEach((String s) -> {
            System.out.print(s + " ");
        });
        System.out.println();
        //lambda实现
        list.sort((o1, o2) -> o1.compareTo(o2));
        list.forEach((String s) -> {
            System.out.print(s + " ");
        });
        System.out.println();

    }
}

(3)Map接口

public class TestDemo {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<>();
        map.put(11, "what");
        map.put(22, "are");
        map.put(33, "you");
        map.put(44, "doing");
        map.put(55, "now");
        map.forEach(new BiConsumer<Integer, String>() {
            @Override
            public void accept(Integer integer, String s) {
                System.out.print("【key:" + integer + "val:" + s + "】 ");
            }
        });
        System.out.println();
        map.forEach((x, y) ->System.out.print("【key:" + x + "val:" + y + "】 "));
        System.out.println();
    }
}

0

评论区