Java 之 Lambda 表达式和 Stream 流

本文详细介绍了Java1.8引入的Lambda表达式和Stream流。Lambda表达式简化了函数式编程,允许将函数作为参数传递。Stream流提供了处理集合的新方式,支持中间操作如skip、limit、sorted和filter,以及终止操作如count、forEach和collect。文章通过实例展示了Lambda和Stream在实际代码中的应用。
摘要由CSDN通过智能技术生成

Lambda 表达式和 Stream 流

1. Lambda 表达式

1.1 Lambda 简介
  1. JDK 1.8 之后的新特性

  2. 平常的方法参数都是引用型数据类型或者基本数据类型

    Lambda 允许把函数接口作为一个方法的参数 (函数作为参数传递进方法中)

  3. Lambda 可以使代码更加简洁,优化代码

1.2 Lambda 格式
(参数) -> {方法体};
三个一,一个小括号,一个箭头,一个大括号
1. 在参数有且仅有一个情况下 () 可以省略
2. 在方法体中执行语句有且只有一行的情况下可以省略 return ;{} 
1.3 匿名内部类与 Lambda 表达式

首先我们要明白对于方法 我们要在意的是 怕【参数】 和 【返回值】,方法名并不重要

1.3.1 无参无返回值
interface Test1 {
    void test();
}

public class Demo1 {
    public static void main(String[] args) {
        // 匿名内部类方式
        testLambda(new Test1() {
            @Override
            public void test() {
                System.out.println("匿名内部类方式");
            }
        });

        // Lambda 表达式
        testLambda(() -> System.out.println("Lambda 方式"));
    }

	public static void testLambda(Test1 test1) {
		test1.test();
	}
}
1.3.2 无参有返回值
interface Supplier<T> {
    T get();
}

public class Demo3 {
    public static void main(String[] args) {

        // 匿名内部类方式
        String s = testLambda(new Supplier<String>() {
            @Override
            public String get() {
                return "这是一个字符串";
            }
        });
        System.out.println(s);

        // Lambda 表达式方式
        String s1 = testLambda(() -> "这也是一个字符串");
        System.out.println(s1);
    }
	public static String testLambda(Supplier<String> s){
		return s.get();
	}
}
1.3.3 有参无返回值
/**
* 自定义的一个消费者接口
*/
@FunctionalInterface
interface Consumer<T> {
    void accept(T t);
}

public class Demo2 {
    public static void main(String[] args) {

        // 匿名内部类方式
        testLambda("春天在哪里", new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });

        // Lambda 表达式方式
        testLambda("春天在哪里", s -> System.out.println(s));

    }

    public static void testLambda(String str, Consumer<String> handle) {
        handle.accept(str);
    }
}
1.3.4 有参有返回值
/**
* 自定义比较器接口
*/
@FunctionalInterface
interface Comparator<T> {
    int compare(T o1, T o2);
}

public class Demo4 {
    public static void main(String[] args) {
        Person[] array = new Person[5];
        Random random = new Random();

        for (int i = 0; i < array.length; i++) {
            // 随机数范围 1 ~ 50
            array[i] = new Person(i + 1, "张三", random.nextInt(50) + 1);
        }
		
         匿名内部类方式
        sortPersonArrayUsingComparator(array, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });

        for (Person person : array) {
            System.out.println(person);
        }
        
        // Lambda 表达式
        sortPersonArrayUsingComparator(array, (p1, p2) -> p1.getId() - p2.getId());

        for (Person person : array) {
            System.out.println(person);
        }
    }

    public static void sortPersonArrayUsingComparator(Person[] array, Comparator<Person> comparator) {
        for (int i = 0; i < array.length - 1; i++) {
            int index = i;
            for (int j = i + 1; j < array.length; j++) {
                // compare 方法的返回值是 int 类型但是值很特殊 > 0 表示前者大 < 0 表示后者大 = 0 表示相等 
                // 我们利用这个判断 如果大于零 交换下标
                if (comparator.compare(array[index], array[j]) > 0){
                    index = j;
                }
            }

            if (index != i) {
                Person temp = array[i];
                array[i] = array[index];
                array[index] = temp;
            }
        }
    }
}

2. Stream 流

2.1 Stream 流概述

JDK 1.8 版本新特性

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

2.2 如何得到 Stream 流对象

Stream 流处理的是集合 或者 数组

对于集合 
Stream<T> stream();
	直接通过 集合对象.Stream(); 来获取流对象。
对于数组
Stream<T> Arrays.Stream(T[] t);
	利用 Arrays 工具类调用 Stream(T[] t); 方法参数为想要获取修的数组参数。

Stream 处理数据的 【中间方法】 返回值还是 Stream 流对象的 称为【中间方法】

常用方法
Stream<T> skip(long n);
	限制跳过当前 Stream 流对应元素的个数,【掐头】
Stream<T> limit(long n);
	限制当前 Stream 对应的元素总个数,【去尾】

Stream<T> sorted();
	对当前 Stream 流存储的进行排序操作,要求元素有自然顺序或者遵从 Comparable 接口,默认【升序】
Stream<T> sorted(Comparator<? super T> com);
	对当前 Stream 流存储的进行排序操作,排序规则由 Comparator 函数式接口规范

Stream<T> filter(Predicate<? super T> pre);
	判断过滤当前 Stream 流可以保存的数据条件,满足条件保留,不满足条件移除,过滤规则由 Predicate 接口约束

Stream<T> distinct();
	当前 Stream 流中对应的所有元素去重擦操作

Stream<R> map(Function<T, R> fun);
	当前 Stream 存储的数据情况转换为 Function 函数式接口要求的返回值类型,完成类型转换操作。

Stream 处理数据的【终止方法】流调用这些方法后返回值类型不再是 Stream 流对象

Stream 流会自动关闭,对应的 Stream 占用的资源空间会被 JVM 收回

long count();
	返回当前 Stream 流对应的数据元素个数,为终止方法。

void forEach(Consumer<? super T> con);
	针对于当前 Stream 存储元素的处置方法,为终止方法。
	
<R, A> R collect(Collector<? super T, A, R> collector);
	Stream 流对应的元素存储内容,转换为用户要求的 集合对象。终止方法
	常用:
		Collectors.toList() 目标存储集合类型为 List 集合
		Collectors.toSet()  目标存储集合类型为 Set 集合
		
Object[] toArray();
	Stream 流存储的元素内容转换为 Object 类型数组返回
2.3 代码演示演示

【中间】方法演示

/**
* Person 为自定义类 属性为 private Integer id;
					   private String name;
					   private Integer age;
*/
public class Demo6 {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        Random random = new Random();

        for (int i = 0; i < 10; i++) {
            list.add(new Person( i + 1, "张三", random.nextInt(50) + 1));
        }

        list.stream()
                .skip(2)
                .limit(8)
            /* 这里使用了 Lambda 表达式 参数为 Comparator 接口需要我们实现的方法为 
            * compare 方法  参数为 两个 
            *			  返回值为 int 类型
            */
                .sorted((p1, p2) -> p1.getAge() - p2.getAge())
            /* 这里使用了 Lambda 表达式 参数为 Predicate 接口 需要我们实现的方法为 
            * test 方法  参数为 1个 
            *			  返回值为 boolean 类型
            */
                .filter(p -> p.getAge() > 20)
            // forEach 为最终方法执行后 Stream 流自动关闭
                .forEach(System.out::println);
        		
    }
}
public class Demo7 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("巴巴托斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电真");
        list.add("小吉祥草王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("灶神马科修斯");
        list.add("流云借风真君");
        list.add("赤王");
        list.add("原初的那一位");

        list.stream()
          		  // 去重
                .distinct()

                /* 这里使用了 Lambda 表达式 参数为 Function 接口 需要我们实现的方法为
                 * apply 方法  参数为 1个
                 *			  返回值为 你需要转换的类型
                 */
                .map(s -> s.toCharArray())
                .forEach(System.out::println);
    }
}

【最终】方法

public class Demo8 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("巴巴托斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电真");
        list.add("小吉祥草王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("灶神马科修斯");
        list.add("流云借风真君");
        list.add("赤王");
        list.add("原初的那一位");

        Stream<String> stream = list.stream();
        /* collect 为最终方法 Collectors.toSet() 将数据存入 set 集合中 
        	set 集合 无序 且 元素不可重复 所以 输出结果会自动去重 且 和添加顺序不一样
        */
        Set<String> collect = stream.collect(Collectors.toSet());
        for (String s : collect) {
            System.out.println(s);
        }
		/*
		 	报错 stream has already been operated upon or closed
		 	Stream 流已经被执行或者关闭 
		 	因为 collect 为最终方法 执行完毕 流自动关闭无法在使用
		*/
        stream.filter(s -> s.length() <= 4).forEach(System.out::println);
    }
}

在这里插入图片描述

public class Demo9 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("巴巴托斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("摩拉克斯");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电影");
        list.add("雷电真");
        list.add("小吉祥草王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("大慈树王");
        list.add("灶神马科修斯");
        list.add("流云借风真君");
        list.add("赤王");
        list.add("原初的那一位");

        // 将集合中元素放入 Object[] 数组中 
        Object[] array = list.stream().distinct().toArray();
        for (Object o : array) {
            System.out.println(o);
        }
        System.out.println();

        // 计算集合中元素个数
        long count = list.stream().count();
        System.out.println(count); // 20
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值