首先是准备工作
Book类
@Data
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Long bookId;
private String bookName;
private String bookCategory;
private String bookIntro;
}
author类
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Author implements Comparable<Author>{
private Long authorId;
private String authorName;
private Integer authorAge;
private String authorIntro;
private List<Book> authorBooks;
@Override
public int compareTo(Author o) {
return this.authorAge-o.getAuthorAge();
}
}
数据的准备
public static List<Author> getAuthors() {
List<Author> authors = new ArrayList<>();
Book book11 = new Book(11L, "11", "哲学,小说", "11intro");
Book book12 = new Book(12L, "12", "哲学,漫画", "12intro");
Book book13 = new Book(13L, "13", "音乐,小说", "13intro");
List<Book> books1 = new ArrayList<>();
books1.add(book11);
books1.add(book12);
books1.add(book13);
Book book21 = new Book(21L, "21", "哲学,小说", "21intro");
Book book22 = new Book(22L, "22", "哲学,漫画", "22intro");
Book book23 = new Book(23L, "23", "音乐,小说", "23intro");
List<Book> books2 = new ArrayList<>();
books2.add(book21);
books2.add(book22);
books2.add(book23);
Book book31 = new Book(31L, "31", "哲学,小说", "31intro");
Book book32 = new Book(32L, "32", "哲学,漫画", "32intro");
Book book33 = new Book(33L, "33", "音乐,小说", "33intro");
List<Book> books3 = new ArrayList<>();
books3.add(book31);
books3.add(book32);
books3.add(book33);
Author author1 = new Author(1L, "张三", 25, "张三,25岁的老作家", books1);
Author author2 = new Author(2L, "李四", 35, "李四,35岁的老作家", books2);
Author author3 = new Author(3L, "王五", 45, "王五,45岁的老作家", books3);
authors.add(author1);
authors.add(author2);
authors.add(author3);
return authors;
}
可以看到,authors里面包含三个作家,其中每个作家又包含着三本书
另外,写lambda表达式的时候,不是说一次就写成功,也不是说死记硬背他的写法,一开始完全可以依赖IDEA的帮助,用下面这个代码举例,可以按照IDEA的提示,filter里面需要我们传入一个 Predicate 的实现对象,那么我就直接new一个匿名内部类,然后写代码,写完之后,然后 alt+回车 让IDEA 帮助我们去转换成 lambda表达式即可
distinct 和 filter 以及 collect
private static void test01单列集合转换成流以及过滤(List<Author> authors) {
List<Author> collect = authors.stream()
.distinct()
.filter(new Predicate<Author>() {
@Override
public boolean test(Author author) {
return author.getAuthorAge() < 40;
}
})
.collect(Collectors.toList());
collect.forEach(a-> System.out.println(a.getAuthorName()+"-->"+a.getAuthorAge()));
}
普通数组转换成流
private static void test02普通数组转换成流() {
Integer[] arr = {1, 2, 3, 4, 3, 6, 6, 6, 6, 6};
Stream<Integer> stream = Arrays.stream(arr);
List<Integer> collect = stream
.distinct() //使用的是equals方法 ,要自己想一下 要不要重写 equals
.collect(Collectors.toList());
for (Integer integer : collect) {
System.out.println("integer = " + integer);
}
}
键值对转换成stream()
private static void test03键值对转换成stream() {
HashMap<String, Integer> map = new HashMap<>();
map.put("zhangsan", 25);
map.put("lisi", 26);
map.put("wangwu", 27);
Set<Map.Entry<String, Integer>> entries = map.entrySet();
List<Map.Entry<String, Integer>> collect = entries.stream()
.filter(entry -> entry.getValue()<40)
.collect(Collectors.toList());
for (Map.Entry<String, Integer> stringIntegerEntry : collect) {
System.out.println(stringIntegerEntry);
}
}
map()
private static void test04_测试map方法(List<Author> authors) {
/* map 类型转换或者是计算,结果替换掉原本的流中的对象 */
List<Integer> collect = authors.stream()
.map(author -> author.getAuthorAge())
.map(integer -> integer + 100)
.collect(Collectors.toList());
for (Integer integer : collect) {
System.out.println(integer);
}
}
sort无参数的使用
private static void test05_sort无参数的使用(List<Author> authors) {
// /*如果出现 sorted()annot be cast to java.lang.Comparable,
// 也就是说 在比较的时候,会把Author转换成Comparable类型进行比较
// ,所以Author要实现Comparable这个接口*/
List<Author> collect = authors.stream()
.sorted()
.collect(Collectors.toList());
for (Author author : collect) {
System.out.println(author);
}
}
sort有参的使用
private static void test06_sort有参的使用(List<Author> authors) {
List<Author> collect = authors.stream()
.sorted(new Comparator<Author>() {
@Override
public int compare(Author o1, Author o2) {
return o1.getAuthorAge() - o2.getAuthorAge();
}
})
.collect(Collectors.toList());
for (Author author : collect) {
System.out.println("author.getAuthorName() = " + author.getAuthorName());
}
}
limit()
private static void test07_测试limit方法(List<Author> authors) {
authors.stream()
.distinct()
.sorted()
.limit(2) //取前两个元素 多余的直接舍弃 不满的话也不影响,就是全部输出
.forEach(author -> System.out.println(author));
}
skip()
private static void test08_skip方法的使用(List<Author> authors) {
authors.stream()
.limit(2)
.skip(1) /*这里比较容易理解 不论是 先跳过还是先限制,都理解成直接截取
限制两个就是直接截取前面两个,后面的直接舍弃,跳过1个就是就是在剩下的流中,跳过第一个,也就是拿第二个,
后面的舍弃*/
.forEach(a -> System.out.println(a));
}
flatMap()
//flatMap 返回一个新的流, flat————>水平的,展平
//如下操作就是把Author集合中的 List<Book>变成一个新的并返回,
//有三个作家,他们的List<Book>变成流之后将会自动的拼接在一起,
//一般的使用场景就是 集合里面放着对象,每个对象里面又有着集合
//我们需要把所有的对象里面的集合拿出来变成一个流
private static void test09_测试flatMap(List<Author> authors) {
List<Book> collect = authors.stream()
.flatMap(new Function<Author, Stream<Book>>() {
@Override
public Stream<Book> apply(Author author) {
return author.getAuthorBooks().stream();
}
})
.collect(Collectors.toList());
for (Book book : collect) {
System.out.println("book = " + book);
}
}
faltMap
private static void test10_测试faltMap的复杂用法(List<Author> authors) {
List<String> collect = authors.stream()
.flatMap(new Function<Author, Stream<Book>>() {
@Override
public Stream<Book> apply(Author author) {
return author.getAuthorBooks().stream();
}
})
.flatMap(new Function<Book, Stream<String>>() {
@Override
public Stream<String> apply(Book book) {
return Arrays.stream(book.getBookCategory().split(","));
}
})
.distinct()
.collect(Collectors.toList());
for (String s : collect) {
System.out.println(s);
}
}
count
private static void test11_终结符之count(List<Author> authors) {
long count = authors.stream()
.count();
System.out.println("count = " + count);
}
max
private static void test12_测试max用法(List<Author> authors) {
Optional<Integer> max = authors.stream()
.map(new Function<Author, Integer>() {
@Override
public Integer apply(Author author) {
return author.getAuthorAge();
}
})
.max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
max.ifPresent(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println("integer = " + integer);
}
});
}
流 转 Set
private static void test14_测试流转Set(List<Author> authors) {
Set<String> collect = authors.stream()
.flatMap((Function<Author, Stream<Book>>) author -> author.getAuthorBooks().stream())
.map(book -> book.getBookName())
.collect(Collectors.toSet());
System.out.println(collect);/*Set 集合是一个 不可重复的集合*/
}
流 转 map
map是一个键值对,所以需要写两个转换方式
private static void test15_流转map集合(List<Author> authors) {
Map<String, List<Book>> collect = authors.stream().
collect(Collectors.toMap(
new Function<Author, String>() {
@Override
public String apply(Author author) {
return author.getAuthorName();
}
},
new Function<Author, List<Book>>() {
@Override
public List<Book> apply(Author author) {
return author.getAuthorBooks();
}
}));
for (Book book : collect.get("张三")) {
System.out.println("book = " + book);
}
}
anymatch()
private static void test16_测试anyMatch(List<Author> authors) {
boolean b = authors.stream().anyMatch(new Predicate<Author>() {
@Override
public boolean test(Author author) {
return author.getAuthorAge() > 40;
}
});
System.out.println("b = " + b);
}
allMatch()
private static void test17_测试AllMathch(List<Author> authors) {
boolean b = authors.stream()
.allMatch(new Predicate<Author>() {
@Override
public boolean test(Author author) {
return author.getAuthorAge() < 110;
}
});
System.out.println(b);
}
reduce 基本的思想就是 给定一个初始值,然后用流中的数据和该初始值做一些运算,运算结束后将运算结果赋值给初始值,类似于
int strat=10;
for(int i=0;i<10;i++){
start=strart+i;
}
常用的reduce方法是 先map 后reduce,也常被称作是 mapreduce格式
Long reduce1 = authors.stream()
.flatMap(new Function<Author, Stream<Book>>() {
@Override
public Stream<Book> apply(Author author) {
return author.getAuthorBooks().stream();
}
})
.map(new Function<Book, Long>() {
@Override
public Long apply(Book book) {
return book.getBookId();
}
})
.reduce(0L, new BinaryOperator<Long>() {
@Override
public Long apply(Long aLong, Long aLong2) {
return aLong + aLong2;
}
});//这里注意一下,0 along along2。需要同一种数据类型,并且0就是along,reduce的操作就是along=along+along2。along2是一直在变化的,along2也就是每一本书的id值。
System.out.println(reduce1);