关于Java8 Lambda表达式的笔记

Java8 Lambda表达式

为什么要引入Lambda表达式

简单说,引入lambda表达式就是为了简化代码,允许将函数作为一个方法的参数传递进方法中;

回顾一下Java8以前,如果想把某个接口的实现类作为参数传递给一个方法会怎么做?要么创建一个类实现该接口,然后new出一个对象,在调用方法时传递进去,要么使用匿名类,可以精简一些代码。以创建一个线程并打印一行日志为例,使用匿名函数写法如下:

new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("欢迎关注公众号:程序新视界");
	}
}).start();

在java8以前,使用匿名函数已经算是很简洁的写法了,再来看看使用Lambda表达式,上面的代码会变成什么样子。

new Thread(() -> System.out.println("欢迎关注公众号:程序新视界")).start();

我们都知道java是面向对象的编程语言,除了部分简单数据类型,万物皆对象。因此,在Java中定义函数或方法都离不开对象,也就意味着很难直接将方法或函数像参数一样传递,而Java8中的Lambda表达式的出现解决了这个问题。

Lambda表达式使得Java拥有了函数式编程的能力,但在Java中Lambda表达式是对象,它必须依附于一类特别的对象类型——函数式接口(functional interface),后面详细讲解。

Lambda表达式简介

Lambda表达式是一种匿名函数(对Java而言这并不完全准确),通俗的说,它是没有声明的方法,即没有访问修饰符、返回值声明和名字的方法。使用Lambda表达式的好处很明显就是可以使代码变的更加简洁紧凑。

Lambda表达式的使用场景与匿名类的使用场景几乎一致,都是在某个功能(方法)只使用一次的时候。

Lambda表达式的语法结构

//没有参数
() -> body

// 1个参数
(param) -> body
// 或
(param) ->{ body; }

// 多个参数
(param1, param2...) -> { body }
// 或
(type1 param1, type2 param2...) -> { body }

代码配合Lombda表达式简洁明了,逻辑清晰(下面有Lomdba表达式语法格式)

import java.util.*;
import java.util.stream.Stream;
/**
 * stream 使用方法
 */
public class stream01 {
    public static void main(String[] args) {
        //声明一个list
        List<String> list = new ArrayList<>();
        list.add("周芷若");
        list.add("张无忌");
        list.add("张三丰");
        list.add("周周");
        //正常情况过滤list元素
        for (String s:list){
            if (s.startsWith("周")){  //筛选姓周的
                System.out.println(s);
            }
        }
        // stream 流  核心理念  只关注实现,不关注如何实现,如fliter只是过滤,forEach只是遍历
        list.stream()
                .filter(aa -> aa.startsWith("周"))       //过滤姓周的
                .filter(aa -> aa.length() == 3)         //过滤长度为3的字符
                .forEach(aa -> System.out.println(aa));  //forEanch遍历
        // 使用stream流有两种模式,1 集合对象获取如 list.stream()   2  stream流静态方法 对象.of
        // 第一种方式示例 集合类
        //List 类
        List<String> lista = new ArrayList<>();
        list.stream();
        //Set 类
        Set<String> set = new HashSet<>();
        set.stream();
        //Map 类
        Map<String, String> map = new HashMap<>();
        //因为集合才能获取stream所以获取键,存储到一个set集合里 获取stream流
        Set<String> set1 = map.keySet();
        set1.stream();
        //获取值,存储到collection集合里,获取stream流
        Collection<String> values = map.values();
        values.stream();
        //这种方式更加简洁,entrSet 可以获取键、值映射关系
        Set<Map.Entry<String, String>> entries = map.entrySet();
        entries.stream();
        //第二种方式使用stream流静态方法of 可以用于数组
        String[] str = {"字符串","字符串"};
        Stream.of(str);
        //Stream流的静态方法of可以传入可变参数,也就是说可以传入数组
        Stream.of("字符串","字符串").forEach(name -> System.out.println(name));
 
// Stream 流 分两种方法
// 1 延迟方法:返回值类型任然是Stream自身类型的方法、因此支持链式调用(除了终结方法外、其余方法都是链式调用)
// 2 终结方法:返回值类型不在是Stream自身类型的方法、因此不支持链式调用
        //Stream常用方法 forEach、filter、Map、Count、limit、skip、concat
        //forEach 方法: 遍历流中的数据属于“终结方法”、遍历之后就不能再调用了
               //获取一个流并遍历,使用Lambda表达式
        Stream.of("熊大","熊二","熊三","熊四","熊五").forEach(name -> System.out.println(name));
        //fliter 方法: 对流中元素进行过滤
        //声明一个流
        Stream<String> stringStream = Stream.of("熊大", "熊二", "李三", "熊四", "熊五");
        //对流中元素进行过滤只要李三、返回值是一个新的流
        Stream<String> stringStream1 = stringStream.filter((String name) -> {
            return name.startsWith("李");
        });
        stringStream1.forEach(name -> System.out.println(name));
//Stream流属于管道流,只能被消费(使用)一次、第一个Stream流调用方法完毕、数据就会流转到下一个Stream流中而第一流就关闭了
       //映射Map方法: 如果需要将流中的元素转换到下一个流中可以使用Map方法
        //声明一个流
        Stream<String> stream = Stream.of("1", "2", "3", "4", "5");   //第一个流
        //使用Map方法把字符转换成整数、转换(映射)为Integer类型整数
        Stream<Integer> integerStream = stream.map((String s) -> {    //第二个流(延迟方法会返回一个新的流)
            return Integer.parseInt(s);
        });
        integerStream.forEach(i -> System.out.println(i));
        //统计Count方法: 用于统计流中元素个数、返回值为long类型、属于终结方法
         ArrayList<Integer> integers =new ArrayList<>();
         integers.add(1);
         integers.add(2);
         integers.add(3);
        Stream<Integer> stream1 = integers.stream();  //返回一个新的流
        long count = stream1.count();
        System.out.println(count);
        //截取limit方法:用于截取流中元素、只能截取前n个、属于延迟方法
        //声明数组
        String[] arr = {"喜洋洋","懒洋洋","灰太狼"};
        //放入流里
        Stream<String> stream2 = Stream.of(arr);
        Stream<String> limit = stream2.limit(2);
        limit.forEach(name -> System.out.println(name));
        //跳过skip方法: 用于跳过、返回一个新的流、属于延迟方法
        String[] arrr = {"喜洋洋","懒洋洋","灰太狼"};
        //放入流里
        Stream<String> stream3 = Stream.of(arrr);
        Stream<String> skip = stream3.skip(2);
        skip.forEach(name -> System.out.println(name));
        //组合concat方法: 将两个流合并一个流
        Stream<String> concat1 = Stream.of("熊大", "熊二", "李三", "熊四", "熊五");
        Stream<String> concat2 = Stream.of("喜洋洋","懒洋洋","灰太狼");
        //把以上两个流组合成一个流
        Stream<String> concat = Stream.concat(concat1, concat2);
        concat.forEach(name -> System.out.println(name));
    }
}

一、Lambda 表达式的基础语法:Java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或 Lambda 操作符

  • 箭头操作符将 Lambda 表达式拆分成两部分:
  • 左侧:Lambda 表达式的参数列表
  • 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体
    语法格式一:无参数,无返回值
  •  () -> System.out.println("Hello Lambda!");
    

语法格式二:有一个参数,并且无返回值

  •  (x) -> System.out.println(x)
    

语法格式三:若只有一个参数,小括号可以省略不写

扫描二维码关注公众号,回复: 8795444 查看本文章
  •  x -> System.out.println(x)
    

语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

Comparator com = (x, y) -> {
System.out.println(“函数式接口”);
return Integer.compare(x, y);
};

语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
Comparator com = (x, y) -> Integer.compare(x, y);
语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
(Integer x, Integer y) -> Integer.compare(x, y);
上联:左右遇一括号省
下联:左侧推断类型省
横批:能省则省
二、Lambda 表达式需要“函数式接口”的支持

  • 函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰
  • 可以检查是否是函数式接口
发布了38 篇原创文章 · 获赞 5 · 访问量 944

猜你喜欢

转载自blog.csdn.net/spring_zhangH/article/details/102646859