java 8 Lambda和Stream流

Lambda和Stream流

1. Lambda 表达式

1.1 概念

对某些匿名内部类的写法优化,特点是可推导可省略。基本格式:(参数列表) -> {代码}

  • 例如:
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("运行线程");
            }
        }).start();

就可以优化为

new Thread(() -> System.out.println("运行线程")).start();

优化规则可以不记,使用Idea快捷键Alt+Enter可以自动优化写法。

2. Stream 流

2.1 概述

java8的Stream使用的是函数式编程,可以对集合或者数组进行链状流式的操作。

2.2 常用操作

2.2.1 创建流

  • 单列集合:集合对象.stream()。实际开发用的最多
  • 数组对象:Arrays.stream(数组)或者Stream.of(数组)
  • 双列集合:转换成单列集合后在创建流。例如:
        HashMap<String, String> map = new HashMap<>();
        map.put("a","A");
        map.put("b","B");
        map.put("c","C");
        Stream<Map.Entry<String, String>> stream = map.entrySet().stream();

流对象的泛型对象就是集合的泛型对象

2.2.2 中间操作

中间操作执行后仍然返回Stream流对象本身。

a. filter

过滤操作,符合条件才能保留在流当中。

        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.stream().filter((item) -> item.startsWith("a")).forEach((item) -> System.out.println(item));// a开头的才能留在流当中

输出结果:

abc
acd

b. map

对流当中的元素计算或者转换。

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("bcd");
        list.add("acd");
        list.stream().map(item->item.toCharArray()).forEach(item-> System.out.println(item.length));//String转换成char数组
        list.stream().map(s->s+"**").forEach(s-> System.out.println(s));//每个元素增加**

输出:

3
3
3
abc**
bcd**
acd**

  • 如果遇到数据量很大的自动装箱操作可以使用maptoint等方法.直接转换为IntStream流.
c. distinct

去重:需要流当中的元素重写hashCode和equals方法。

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("bcd");
        list.add("acd");
        list.add("acd");
        list.stream().distinct().forEach(s-> System.out.println(s));//输出:abc bcd acd
d. sorted

对流中的元素排序:该方法俩个重载方法可以在sorted中通过入参匿名内部类定义比较 也可以流中的元素本身实现Comparator接口

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("bcd");
        list.add("acd");
        list.add("acd");
        list.stream().sorted().forEach(s-> System.out.println(s));
e. limit

设置流的最大长度,超出部分将被抛弃。

d.skip

跳过流的前n和元素,在返回后面所有元素。

  • 组合技:limit和skip实现分页
        int pageSize = 10;
        int pageIndex = 7;

        List<Integer> expected = Arrays.asList(61, 62, 63, 64, 65, 66, 67, 68, 69, 70);
        List<Integer> result = Stream.iterate(1, i -> i + 1)
                .skip((pageIndex - 1) * pageSize)
                .limit(pageSize)
                .collect(Collectors.toList());

        assertEquals(expected, result);
e.flatmap

与map不同的是,flatmap可以把一个对象转换成多个对象作为流当中的元素。

package org.example;

import java.util.*;

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

        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("mike");
        ArrayList<User> userArrayList = new ArrayList<>();
        userArrayList.add(new User(1, list));
        userArrayList.add(new User(2, list));
        // 要求输出userArrayList里边所有人的所有名字
        userArrayList.stream()
                .flatMap(user -> user.name.stream())
                .forEach(name -> System.out.println(name));
    }
}

class User {
    public User(int age, List<String> name) {
        this.age = age;
        this.name = name;
    }

    public int age;
    public List<String> name;
}
image
f.parallel

转换为串行流,可以用peek方法来打印查看数据被哪个线程处理.

  • 也可以通过parallelStream 方法直接获取串行流.

2.2.3 终结操作

执行终结操作后链式编程结束,遍历或者返回一个对象。

a. forEach

遍历流本身。

b. count

计算流的size。

c. max和min

流当中的最值,比较同sort方法的使用。

d. collect

把当前流转换成一个集合。

  • 转换成list

collect 方法的入参直接使用Collectors就可以。

package org.example;

import java.util.*;
import java.util.stream.Collectors;

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

        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("mike");
        ArrayList<User> userArrayList = new ArrayList<>();
        userArrayList.add(new User(1, list));
        userArrayList.add(new User(2, list));
        // 要求转换成list<name>
        List<String> names = userArrayList.stream()
                .flatMap(user -> user.name.stream())
                .collect(Collectors.toList());
        

    }
}

class User {
    public User(int age, List<String> name) {
        this.age = age;
        this.name = name;
    }

    public int age;
    public List<String> name;
}
  • 转换成map
package org.example;

import java.util.*;
import java.util.stream.Collectors;

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

        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("mike");
        ArrayList<User> userArrayList = new ArrayList<>();
        userArrayList.add(new User(1, list));
        userArrayList.add(new User(2, list));
        // 要求转换成map<age,names>
        Map<Integer, List<String>> collect = userArrayList.stream()
                .collect(Collectors.toMap(user -> user.age, user -> user.name));
    }
}

class User {
    public User(int age, List<String> name) {
        this.age = age;
        this.name = name;
    }

    public int age;
    public List<String> name;
}
e. 查找匹配操作

顾名思义 推一举三即可

  • anyMatch 是否匹配
image
  • allMatch

  • noneMatch

  • findAny(随机获取一个元素)

  • findFirst(获取第一个元素)

f. reduce(归并)

对流中的数据按照自定义的方式累计计算得出一个结果。

具体方式是:

image
package org.example;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;

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

        List<String> list = new ArrayList<>();
        list.add("张三");
        list.add("mike");
        ArrayList<User> userArrayList = new ArrayList<>();
        userArrayList.add(new User(1, list));
        userArrayList.add(new User(2, list));
        // 计算累计年龄
        Integer reduce = userArrayList.stream().map(user -> user.age)
                .reduce(0, new BinaryOperator<Integer>() {
                    @Override
                    public Integer apply(Integer result, Integer item) {
                        return result + item;
                    }
                });
      
              Integer reduce = userArrayList.stream().map(user -> user.age)
                .reduce(0, (result, item) -> result + item);//简略写法

    }
}

class User {
    public User(int age, List<String> name) {
        this.age = age;
        this.name = name;
    }

    public int age;
    public List<String> name;
}
image

2.3注意

  • 惰性求值:没有终结操作,中间操作不会执行。
  • 流是一次性的,只能使用一次终结操作,第二次会报错。
  • 流不会影响原来的数据,这也是我们所期望的。

学习up主三更草堂的视频记录的笔记。

posted @ 2023-08-13 19:20  ZyaOo  阅读(131)  评论(0)    收藏  举报