Day 03 - Lambda和Stream流

Lambda和Stream流

1.lambda概述

​ Lambda 规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。

​ Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代码结构。

语法形式

​ () -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符 ,读作(goes to)。

语法简化

  //1.简化参数类型,可以不写参数类型,但是必须所有参数都不写
        NoReturnMultiParam lamdba1 = (a, b) -> {
            System.out.println("简化参数类型");
        };
        lamdba1.method(1, 2);

  //2.简化参数小括号,如果只有一个参数则可以省略参数小括号
        NoReturnOneParam lambda2 = a -> {
            System.out.println("简化参数小括号");
        };
        lambda2.method(1);

  //3.简化方法体大括号,如果方法条只有一条语句,则可以省略方法体大括号
        NoReturnNoParam lambda3 = () -> System.out.println("简化方法体大括号");
        lambda3.method();

  //4.如果方法体只有一条语句,并且是 return 语句,则可以省略方法体大括号
        ReturnOneParam lambda4 = a -> a + 3;
        System.out.println(lambda4.method(5));

		ReturnMultiParam lambda5 = (a, b) -> a + b;
        System.out.println(lambda5.method(1, 1));
@FunctionalInterface  // 函数式接口 , 标识着只能有一个需要被实现的方法 。 

lambda 表达式引用方法

​ 有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以可以利用 lambda表达式的接口快速指向一个已经被实现的方法。

​ 语法 : 方法归属者::方法名 静态方法的归属者为类名,普通方法归属者为对象或者this。

​ 如果时构造方法的引用 通过 类名::new 的方式来实现。

要求:

​ 1.参数数量和类型要与接口中定义的一致

​ 2.返回值类型要与接口中定义的一致

​ 3.构造的方法引用同上

	returnOneParam lambda1 = a -> doubleNum(a); // ==
	//lambda2 引用了已经实现的静态 doubleNum 方法
    ReturnOneParam lambda2 = Exe1::doubleNum;

	//lambda4 引用了已经实现的非静态 addTwo 方法
    ReturnOneParam lambda4 = exe::addTwo;

	ItemCreatorBlankConstruct creator = () -> new Item();
	 ItemCreatorBlankConstruct creator2 = Item::new;

遍历集合

	ArrayList<Integer> list = new ArrayList<>();
	Collections.addAll(list, 1,2,3,4,5);
	//lambda表达式 方法引用
	list.forEach(System.out::println);


	ArrayList<Item> items = new ArrayList<>();
	items.add(new Item(11, "小牙刷", 12.05 ));
	items.add(new Item(5, "日本马桶盖", 999.05 ));
	items.add(new Item(7, "格力空调", 888.88 ));
	items.add(new Item(17, "肥皂", 2.00 ));
	items.add(new Item(9, "冰箱", 4200.00 ));
	// 删除Item 对象中 id = 7 。
	items.removeIf(ele -> ele.getId() == 7);

	//通过 foreach 遍历,查看是否已经删除
	items.forEach(System.out::println);

集合内元素排序

​ 在以前我们若要为集合内的元素排序,就必须调用 sort 方法,传入比较器匿名内部类重写 compare 方法,我们现在可以使用 lambda 表达式来简化代码

ArrayList<Item> list = new ArrayList<>();
list.add(new Item(13, "背心", 7.80));
list.add(new Item(11, "半袖", 37.80));
list.add(new Item(14, "风衣", 139.80));
list.add(new Item(12, "秋裤", 55.33));
/*
list.sort(new Comparator<Item>() {
    @Override
    public int compare(Item o1, Item o2) {
        return o1.getId()  - o2.getId();
    }
});
*/
// 升序: 排序
list.sort((o1, o2) -> o1.getId() - o2.getId());
System.out.println(list);

2.Stream处理集合

在这里插入图片描述

​ Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

​ Stream可以由数组或集合创建,对流的操作分为两种:

  1. 中间操作,每次返回一个新的流,可以有多个

  2. 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

  3. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。

  4. stream不会改变数据源,通常情况下会产生一个新的集合或一个值

  5. stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行

Stream流的创建

​ Stream可以通过集合数组创建。

1、通过 java.util.Collection.stream() 方法用集合创建流

2、使用java.util.Arrays.stream(T[] array)方法用数组创建流

3、使用Stream的静态方法:of()、iterate()、generate()

public class StreamCreateType {
    public static void main(String[] args) {
        //1. Collection.stream()方法用集合创建
        List<String> list = Arrays.asList("1","2","3");
        // 创建一个顺序流
        Stream<String> stream = list.stream();
        // 创建一个并行流
        Stream<String> stringStream = list.parallelStream();
        List<String> collect = stringStream.collect(Collectors.toList());

        //2. Arrays.stream(T[] array) 方法用数组创建
        int[] array={1,2,3,4,5};
        IntStream stream1 = Arrays.stream(array);
        System.out.println(stream1.max().getAsInt());

        //3.  使用Stream的静态方法:of()、iterate()、generate()
        Stream<Integer> intStream = Stream.of(1, 2, 3, 4, 5, 6);
        Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
        // 0 3 6 9
        stream2.forEach(System.out::println);

        AtomicInteger m = new AtomicInteger(10);
        Stream<Integer> stream3 = Stream.generate(()-> m.getAndIncrement()).limit(3);
        //10 11 12
        stream3.forEach(System.out::println);
    }
}

Stream流的使用

1.遍历和筛选foreach 和 filter
List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

//1. 顺序遍历
    list.forEach(System.out::println);
    System.out.println("=====================");

//筛选出Integer集合中大于7的元素,并打印出来 filter 筛选
    List<Integer> list = Arrays.asList(6, 7, 3, 8, 1, 2, 9);
    Stream<Integer> stream = list.stream();
    stream.filter(x -> x > 7)..collect(Collectors.toList()).forEach(System.out::println);
	
List<Item> collect = items.stream().filter(item -> item.id > 7).collect(Collectors.toList());

2.聚合(max / min / Count)映射(map)
		// 找出数字的最大值
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Integer integer = list.stream().max(((o1, o2) -> o1 - o2)).get();
        System.out.println("integer = " + integer);

		// 找出最长的字符串
        List<String> myList = Arrays.asList("李磊", "韩梅梅", "Lucy", "Jim");
        String s = myList.stream().max(((o1, o2) -> o1.length() - o2.length())).get();
        System.out.println("s = " + s);

		  //4 . 计算Integer集合中大于6的元素的个数
   	 	List<Integer> list4 = Arrays.asList(7, 6, 4, 8, 2, 11, 9);
    	long count = list4.stream().filter(x -> x > 6).count();
    	System.out.println("list中大于6的元素个数:" + count);
map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

//1. 英文字符串数组的元素全部改为大写。
    String[] strArr = { "abcd", "bcdd", "defde", "fTr" };
    List<String> strList1 = Arrays.stream(strArr).map(str -> str.toUpperCase()).collect(Collectors.toList());
				            
//整数数组每个元素+3。
    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("每个元素+3:" + intListNew);
// 取名字 成一个
ArrayList<Item> items = new ArrayList<>();
        items.add(new Item(11, "小牙刷", 12.05));
        items.add(new Item(5, "日本马桶盖", 999.05));
        items.add(new Item(7, "格力空调", 888.88));
        items.add(new Item(17, "肥皂", 2.00));
        items.add(new Item(9, "冰箱", 4200.00));

        List<String> collect = items.stream()
                .map(item -> item.name)
                .collect(Collectors.toList());
        collect.forEach(System.out::println);
3.归约和收集(reduce) 计算
	//1. 求Integer集合的元素之和、乘积和最大值
    List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
    // 求和方式1
    Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
	
	// 求乘积
    Optional<Integer> product = list.stream().reduce((x, y) -> x * y);
    // 求最大值方式1
    Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);

	// 求工资之和方式1:
    Optional<Integer> sumSalary = personList.stream().map(Person::getSalary).reduce(Integer::sum);
// 收集
collect(Collectors.toList());

collect(Collectors.toSet());
4.统计与分组

统计:

Collectors提供了一系列用于数据统计的静态方法:
计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble
 		list.add(new Person("张三", 3000, 23, "男", "武汉"));
        list.add(new Person("李四", 4000, 24, "男", "合肥"));
        list.add(new Person("王五", 5000, 25, "女", "武汉"));
        list.add(new Person("赵六", 6000, 26, "男", "北京"));
        list.add(new Person("田七", 7000, 27, "女", "北京"));
        list.add(new Person("王八", 8000, 28, "男", "武汉")); 

// 球总数
        Long count = list.stream().collect(Collectors.counting());
        System.out.println(count);
        // 求平均
        Double avg = list.stream().collect(Collectors.averagingDouble(Person::getSalary));
        System.out.println(avg);
        // 求最高工资
        Person person = list.stream().collect(Collectors.maxBy(((o1, o2) -> o1.getSalary() - o2.getSalary()))).get();
        System.out.println(person);
        // 求工资之和
        Integer sum = list.stream().collect(Collectors.summingInt(Person::getSalary));
        System.out.println(sum);
        // 统计以上所有信息
        DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(Person::getSalary));
        System.out.println(collect);

分组

 /**
     * 分组
     * @param args
     */
    public static void main8(String[] args) {
        Map<String, List<Person>> listMap = list.stream().collect(Collectors.groupingBy(Person::getSex));
        for (Map.Entry<String, List<Person>> entry : listMap.entrySet()) {
            System.out.println(entry.getKey());
            List<Person> list1 = entry.getValue();
            list1.forEach(System.out::println);
        }
        System.out.println("=================================================================");
        Map<String, List<Person>> listMap1 = list.stream().collect(Collectors.groupingBy(Person::getArea));
        for (Map.Entry<String, List<Person>> entry : listMap1.entrySet()) {
            System.out.println(entry.getKey());
            List<Person> list1 = entry.getValue();
            list1.forEach(System.out::println);
        }
        System.out.println("=================================================================");
        Map<String, Map<String, List<Person>>> map = list.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
        String s = JSON.toJSONString(map);
        System.out.println(s);
    }
5.接合
/**
     * 接合 ( 按照 , 进行拼接)
     * @param args
     */
    public static void main9(String[] args) {
        String s = list.stream().map(Person::getName).collect(Collectors.joining(","));
        System.out.println(s);
    }
6.排序和提取

sorted,中间操作。有两种排序:

​ 1. sorted():自然排序,流中元素需实现Comparable接口

​ 2. sorted(Comparator com):Comparator排序器自定义排序

/**
     * 排序
     * @param args
     */
    public static void main10(String[] args) {
        List<Person> list = Demo4.list.stream().sorted(((o1, o2) -> o2.getSalary() - o1.getSalary())).collect(Collectors.toList());
        list.forEach(System.out::println);
    }

流也可以进行合并、去重、限制、跳过等操作。

 List<String> list1 = Arrays.asList("a", "b", "c", "d", "e");
        List<String> list2 = Arrays.asList("d", "e", "f", "g");
        Stream<String> stream1 = list1.stream();
        Stream<String> stream2 = list2.stream();
		// 合并流 +  去重操作
        List<String> list3 = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());

 List<Integer> list4 = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);	
		// limit 为取 10 条数据
        List<Integer> list5 = list4.stream().limit(10).collect(Collectors.toList());
        System.out.println(list5);
		// skip 为跳过 5 条数据 取10条数据
        List<Integer> list6 = list4.stream().skip(5).limit(10).collect(Collectors.toList());
        System.out.println(list6);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值