Lambda表达式是JDK8的新特性,他可以对某些匿名内部类的写法进行简写(匿名内部类是一个结果,并且它当中只有一个抽象方法被重写,即可使用,它不关注方法,但是关注方法参数和方法体)
(参数列表) -> {代码}
//练习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);
}
Stream也是java8中新特性,它可以被用来对集合或数组进行链状流式的操作,从而方便对数组和集合操作
单例集合 : 集合对象.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();
提前数据准备
// 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
private static void test1() {
List<Author> authors = getAuthors();
authors.stream().distinct()
.filter(author -> author.getAge() > 15) // 过滤条件
.forEach(author -> System.out.println(author.getName())); // 结束操作
}
可以把流中的元素进行计算或转换。
// 案例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));
}
去除流中的重复元素
注意:distinct方法是依赖Object的equals方法来判断是否是相同对象,所以需要重写equals方法。
对流中的元素进行排序
方法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()));
}
可以设置流的最大长度
// 案例
private static void test3() {
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.sorted()
.limit(2)
.forEach(author -> System.out.println(author.getAge()));
}
跳过流中的前n个元素,返回剩下的元素。
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); // 采用引用方法
}
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());
}
把当前流转换成一个集合
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);
}
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()));
}
对流中的数据按照指定的计算方式计算出一个结果
携带两个参数的源码
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);
}
惰性求值:如果没有终结操作,中间操作是不会得到执行的。
流是一次性的:一旦一个流对象经过一个终结操作后,这个流就不能再被使用了,只能重新创建流对象再使用。
不会影响原数据的大小
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()));
}
}