java8新特性“Lambda&Stream“

Lambda&Stream

目录

        • 1、Lambda表达式
          • 1.1 概念
          • 1.2 基本格式
          • 1.3 练习
          • 1.4 规则
        • 2、Stream流
          • 2.1 概念
          • 2.2 创建流
          • 2.3 stream常用操作
            • 1、filter
            • 2、map
            • 3、distinct
            • 4、sorted
            • 5、limit
            • 6、skip
            • 7、flatMap
            • 8、结束操作
            • 4、collect
            • 5、查找与匹配
            • 6、reduce归并
          • 2.4、 使用流注意事项
          • 综合案例

1、Lambda表达式
1.1 概念

Lambda表达式是JDK8的新特性,他可以对某些匿名内部类的写法进行简写(匿名内部类是一个结果,并且它当中只有一个抽象方法被重写,即可使用,它不关注方法,但是关注方法参数和方法体)

1.2 基本格式
(参数列表) -> {代码}
1.3 练习
//练习1: Lambda在创建线程使用
public class LambdaThread {
    public static void main(String[] args) {
        new Thread(()-> {
                System.out.println("新线程被创建");
        }).start();
    }
}

练习2

// 练习2  
int calculate = Calculate(new IntBinaryOperator() {
            @Override
            public int applyAsInt(int left, int right) {
                return left + right;
            }
        });
        System.out.println(calculate);

    }
// IntBinaryOperator 是一个interface
    public static int Calculate(IntBinaryOperator operator) {
        int a = 10;
        int b = 20;
        return operator.applyAsInt(a, b);
    }

匿名内部类 优化成Lambda表达式

// 练习2  
int calculate = Calculate(new IntBinaryOperator() {
     int sum = calculateNum((int left, int right) -> {
        return left + right;
    });
    System.out.println(sum);
}
// IntBinaryOperator 是一个interface
    public static int Calculate(IntBinaryOperator operator) {
        int a = 10;
        int b = 20;
        return operator.applyAsInt(a, b);
    }
1.4 规则
  • 参数类型可以省略
  • 方法体只有一句代码时 大括号return和唯一一句代码的分号可以省略
  • 方法只有一个参数时 小括号可以省略
2、Stream流
2.1 概念

Stream也是java8中新特性,它可以被用来对集合或数组进行链状流式的操作,从而方便对数组和集合操作

2.2 创建流

单例集合 : 集合对象.stream()

// 集合对象.stream()
List<Integer> list = new ArrayList<>();
Stream<Integer> stream = list.stream();

数组Arrays.stream(数组)Stream.of(数组) 来创建

// Arrays.stream(数组)  或 Stream.of(数组) 来创建
Integer[] arr = {1,5,7,9};
Stream<Integer> stream1 = Arrays.stream(arr);
Stream<Integer> stream2 = Stream.of(arr);

双例集合:转换成单例集合后再创建

Map<Integer, String> map = new HashMap<>();
Stream<Map.Entry<Integer, String>> stream3 = map.entrySet().stream();
2.3 stream常用操作

提前数据准备

  //  Author
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class Author implements Comparable<Author>{
    private Long id;
    private String name;
    private Integer age;
    private String intro;
    private List<Book> books;

    @Override
    public int compareTo(Author o) {
        return this.age - o.getAge();
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {
    private Long id;
    private String name;
    private String category;
    private Integer score;
    private String intro;
}

插入数据

private static List<Author> getAuthors() {
        Author author = new Author(1L, "蒙多", 17, "三体", null);
        Author author2 = new Author(2L, "亚拉索", 18, "平凡世界", null);
        Author author3 = new Author(3L, "易大师", 19, "瓦尔登湖", null);
        Author author4 = new Author(3L, "易大师", 19, "猫", null);

        List<Book> book1 = new ArrayList<>();
        List<Book> book2 = new ArrayList<>();
        List<Book> book3 = new ArrayList<>();
        List<Book> book4 = new ArrayList<>();

        book1.add(new Book(1L, "刘慈欣", "哲学,爱情", 80, "*"));
        book1.add(new Book(2L, "老舍", "爱情,个人成长", 80, "**"));

        book2.add(new Book(3L, "刘同", "爱情,传记", 70, "***"));
        book2.add(new Book(3L, "大兵", "个人成长,传记", 70, "****"));
        book2.add(new Book(4L, "莫言", "哲学", 70, "*****"));

        book3.add(new Book(5L, "张爱玲", "个人成长", 60, "******"));
        book3.add(new Book(6L, "三毛", "传记", 60, "*******"));
        book3.add(new Book(6L, "曹雪芹", "爱情", 60, "********"));

        book4.add(new Book(5L, "罗贯中", "个人成长", 60, "******"));
        book4.add(new Book(6L, "施耐庵", "个人成长,传记,爱情", 60, "*******"));
        book4.add(new Book(6L, "奥斯特", "哲学,爱情,个人成长", 60, "********"));


        author.setBooks(book1);
        author2.setBooks(book2);
        author3.setBooks(book3);
        author4.setBooks(book4);

        return new ArrayList<>(Arrays.asList(author, author2, author3, author4));
    }
1、filter

对流中的元素进行条件过滤,筛选符合条件的放在流中

// 案例1
private static void test1() {
        List<Author> authors = getAuthors();
        authors.stream().distinct()
                .filter(author -> author.getAge() > 15) // 过滤条件
                .forEach(author -> System.out.println(author.getName())); // 结束操作
    }
2、map

可以把流中的元素进行计算或转换。

// 案例2
public static void test() {
    List<Author> authors = getAuthors();
    authors.stream()
            .map(author -> author.getAge())
            .map(age -> age+10)
            .forEach(age -> System.out.println(age));
}
3、distinct

去除流中的重复元素

注意:distinct方法是依赖Object的equals方法来判断是否是相同对象,所以需要重写equals方法。

4、sorted

对流中的元素进行排序

方法1:调用sorted()空参方法

在比较的实体类上要实现Comparable接口,不然会报类型不匹配的异常。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1WCgGaMb-1671724742163)(C:\Users\geticsen\AppData\Roaming\Typora\typora-user-images\image-20221221223637189.png)]

// 案例
    private static void test2() {
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .forEach(author -> System.out.println(author.getAge()));

    }

// 结果
17
18
19
19

方法2:在sorted方法中实现Comparator接口

// 案例
public static void test2() {
    List<Author> authors = getAuthors();
    authors.stream()
            .distinct()
            .sorted((o1, o2) -> o1.getAge()-o2.getAge())
            .forEach(author -> System.out.println(author.getAge()));
}
5、limit

可以设置流的最大长度

// 案例 
private static void test3() {
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .limit(2)
                .forEach(author -> System.out.println(author.getAge()));
    }

6、skip

跳过流中的前n个元素,返回剩下的元素。

7、flatMap

map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

// 打印所有书籍的名字,要求对重复的元素进行去重。
// 法1 : flatMap
    private static void test4() {
        List<Author> authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .forEach(book -> System.out.println(book.getName()));
    }
// 法2 :Map
        authors.stream()
                .map(author -> author.getBooks())
                .forEach(books -> {
                    for (Book book:books){
                        System.out.println(book.getName());
                    }
                });

案例2: 打印现有数据的所有分类,要求对分类进行去重。不能出现这种格式:哲学,爱情,要将它们拆开输出

    private static void test5() {
        List<Author> authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(System.out::println);  // 采用引用方法

    }

8、结束操作

1、foreach

2、**count ** 获取当前流中元素的个数。

    private static void test6() {
        List<Author> authors = getAuthors();
        long count = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .count();
        System.out.println(count);

    }

3、max&min

//分别获取这些作家所出书籍的最高分和最低分
public static void test7() {
    List<Author> authors = getAuthors();
    Optional<Integer> max = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .map(book -> book.getScore())
            .max((o1, o2) -> o1 - o2);
    Optional<Integer> min = authors.stream()
            .flatMap(author -> author.getBooks().stream())
            .map(book -> book.getScore())
            .min(((o1, o2) -> o1 - o2));
    System.out.println(max.get());
    System.out.println(min.get());
}
4、collect

把当前流转换成一个集合

list集合

// 获取一个存放所有作者名字的list集合
private static void test8() {
        List<Author> authors = getAuthors();
        List<String> collect = authors.stream().
                map(author -> author.getName())
                .collect(Collectors.toList());
        System.out.println(collect);
    }

set集合

// 获取一个存放所有作者名字的set集合
private static void test9() {
        List<Author> authors = getAuthors();
        Set<String> collect2 = authors.stream().
                map(author -> author.getName())
                .collect(Collectors.toSet());
        System.out.println(collect2);
    }

map集合

// 获取一个Map集合,map的key为作者名,value为List
    public static void test10() {
        List<Author> authors = getAuthors();
        Map<String, List<Book>> map = authors.stream()
                .collect(Collectors.toMap(Author::getName, Author::getBooks));

        System.out.println(map);
    }
5、查找与匹配

anyMatch

判断是否有任意符合匹配条件的元素,结果为boolean类型。

// 判断是否有作家年龄在19以上
private static void test11() {
        List<Author> authors = getAuthors();
        boolean b = authors.stream()
                .anyMatch(author -> author.getAge() >19);
        System.out.println(b);
    }

allMatch

判断是否都符合匹配条件的元素,结果为boolean类型。

// 判断是否有所有作家年龄在19以上
private static void test12() {
        List<Author> authors = getAuthors();
        boolean b = authors.stream()
                .allMatch(author -> author.getAge() >19);
        System.out.println(b);
    }

noneMatch

断流中的元素是否都不符合匹配条件,如果都不符合结果为true,否则结果为false

findAny

获取流中的任意一个元素,无法保证是第一个元素

//获取任意一个年龄大于18的作家,如果存在就输出他的名字
 private static void test13() {
        List<Author> authors = getAuthors();
        Optional<Author> any = authors.stream()
                .filter(author -> author.getAge() > 19)
                .findAny();
        any.ifPresent(author -> System.out.println(author.getName()));
    }

findFirst

获取流中的第一个元素。

// 获取一个年龄最小的作家,并输出他的姓名  
private static void test14() {
        List<Author> authors = getAuthors();
        Optional<Author> first = authors.stream()
                .sorted(((o1, o2) -> o1.getAge() - o2.getAge()))
                .findFirst();
        first.ifPresent(author -> System.out.println(author.getName()));
    }
6、reduce归并

对流中的数据按照指定的计算方式计算出一个结果

携带两个参数的源码

T result = identity;
for (T element : this stream)
	result = accumulator.apply(result, element)
return result;

identity  方法参数传入的初始值
accumulator.apply   通过方法参数来确定如何计算

案例1:使用reduce求所有作者年龄的和

//  使用reduce求所有作者年龄的和
private static void test14() {
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                .reduce(0, (result, element) -> result + element);
        System.out.println(reduce);
    }

案例2: 使用reduce求所有作者中年龄的最大值

// 使用reduce求所有作者中年龄的最大值
private static void test15() {
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, (result, element) -> result > element ? result : element);
        System.out.println(reduce);
    }
2.4、 使用流注意事项
  • 惰性求值:如果没有终结操作,中间操作是不会得到执行的。

  • 流是一次性的:一旦一个流对象经过一个终结操作后,这个流就不能再被使用了,只能重新创建流对象再使用。

  • 不会影响原数据的大小

综合案例
public class StreamDemo {

    private static List<Author> getAuthors() {
        Author author = new Author(1L, "蒙多", 17, "三体", null);
        Author author2 = new Author(2L, "亚拉索", 18, "平凡世界", null);
        Author author3 = new Author(3L, "易大师", 19, "瓦尔登湖", null);
        Author author4 = new Author(3L, "易大师", 19, "猫", null);

        List<Book> book1 = new ArrayList<>();
        List<Book> book2 = new ArrayList<>();
        List<Book> book3 = new ArrayList<>();
        List<Book> book4 = new ArrayList<>();

        book1.add(new Book(1L, "刘慈欣", "哲学,爱情", 80, "*"));
        book1.add(new Book(2L, "老舍", "爱情,个人成长", 80, "**"));

        book2.add(new Book(3L, "刘同", "爱情,传记", 70, "***"));
        book2.add(new Book(3L, "大兵", "个人成长,传记", 70, "****"));
        book2.add(new Book(4L, "莫言", "哲学", 70, "*****"));

        book3.add(new Book(5L, "张爱玲", "个人成长", 60, "******"));
        book3.add(new Book(6L, "三毛", "传记", 60, "*******"));
        book3.add(new Book(6L, "曹雪芹", "爱情", 60, "********"));

        book4.add(new Book(5L, "罗贯中", "个人成长", 60, "******"));
        book4.add(new Book(6L, "施耐庵", "个人成长,传记,爱情", 60, "*******"));
        book4.add(new Book(6L, "奥斯特", "哲学,爱情,个人成长", 60, "********"));


        author.setBooks(book1);
        author2.setBooks(book2);
        author3.setBooks(book3);
        author4.setBooks(book4);

        return new ArrayList<>(Arrays.asList(author, author2, author3, author4));
    }

    public static void main(String[] args) {
        // test1(); // 获取到作家的集合,打印出年龄小于18的作家的名字
        // test2(); // 对流中的元素按照年龄进行降序排序,并且要求不能有重复元素,
        // test3(); // 对流中的元素按照年龄进行降序排序,并且要求不能有重复元素,打印其中年龄最大的两个作家。
        // test4(); // 打印所有书籍的名字,要求对重复的元素进行去重。
        // test5(); // 打印现有数据的所有分类,要求对分类进行去重。不能出现这种格式:哲学,爱情,要将它们拆开输出。
        // test6(); // 大印这些作家的所出书籍的数量
        // test7(); // 分别获取这些作家书籍的最高分和最低分
        // test8(); // 获取一个存放所有作者名字的list集合
        // test9(); // 获取一个存放所有作者名字的set集合
        // test10(); // 获取一个Map集合,map的key为作者名,value为List
        // test11(); // 判断是否有作家年龄在18以上
        // test12(); // 获取任意一个年龄大于18的作家,如果存在就输出他的名字
        // test13(); // 获取一个年龄最小的作家,并输出他的姓名
        // test14(); //使用reduce求所有作者年龄的和
        test15(); //使用reduce求所有作者中年龄的最大值
    }

    private static void test15() {
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .map(author -> author.getAge())
                .reduce(Integer.MIN_VALUE, (result, element) -> result > element ? result : element);
        System.out.println(reduce);
    }

    private static void test14() {
        List<Author> authors = getAuthors();
        Integer reduce = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                .reduce(0, (result, element) -> result + element);
        System.out.println(reduce);
    }

    private static void test13() {
        List<Author> authors = getAuthors();
        Optional<Author> first = authors.stream()
                .sorted(((o1, o2) -> o1.getAge() - o2.getAge()))
                .findFirst();
        first.ifPresent(author -> System.out.println(author.getName()));
    }

    private static void test12() {
        List<Author> authors = getAuthors();
        Optional<Author> any = authors.stream()
                .filter(author -> author.getAge() > 19)
                .findAny();
        any.ifPresent(author -> System.out.println(author.getName()));
    }

    private static void test11() {
        List<Author> authors = getAuthors();
        boolean b = authors.stream()
                .anyMatch(author -> author.getAge() > 19);
        System.out.println(b);
    }

    public static void test10() {
        List<Author> authors = getAuthors();
        Map<String, List<Book>> map = authors.stream()
                .collect(Collectors.toMap(Author::getName, Author::getBooks));

        System.out.println(map);
    }


    private static void test9() {
        List<Author> authors = getAuthors();
        Set<String> collect2 = authors.stream().
                map(author -> author.getName())
                .collect(Collectors.toSet());
        System.out.println(collect2);
    }

    private static void test8() {
        List<Author> authors = getAuthors();
        List<String> collect = authors.stream().
                map(author -> author.getName())
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    private static void test7() {

        List<Author> authors = getAuthors();
        Optional<Integer> max = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .max((o1, o2) -> o1 - o2);
        Optional<Integer> min = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .map(book -> book.getScore())
                .min(((o1, o2) -> o1 - o2));
        System.out.println(max.get());
        System.out.println(min.get());

    }

    private static void test6() {
        List<Author> authors = getAuthors();
        long count = authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .count();
        System.out.println(count);

    }

    private static void test5() {
        List<Author> authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(System.out::println);

    }

    private static void test4() {
        List<Author> authors = getAuthors();

//        // 法1:flatMap
//        authors.stream()
//                .flatMap(author -> author.getBooks().stream())
//                .forEach(book -> System.out.println(book.getName()));
        // 法2:Map
        authors.stream()
                .map(author -> author.getBooks())
                .forEach(books -> {
                    for (Book book : books) {
                        System.out.println(book.getName());
                    }
                });

    }

    private static void test3() {
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .limit(2)
                .forEach(author -> System.out.println(author.getAge()));
    }

    private static void test2() {
        List<Author> authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted()
                .forEach(author -> System.out.println(author.getAge()));

    }

    //获取到作家的集合,打印出年龄小于18的作家的名字
    private static void test1() {
        List<Author> authors = getAuthors();
        authors.stream().distinct()
                .filter(author -> author.getAge() > 18)
                .forEach(author -> System.out.println(author.getName()));
    }

}

你可能感兴趣的:(java,jvm,开发语言)