概述
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {
//id
private Long id;
//书名
private String name ;
//分类
private String category;
//评分
private Integer score;
//简介
private String intro;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode //用于后期的去重使用
public class Author {
private Long id;//id
private String name;//姓名
private Integer age;//年龄
private String intro;//简介
private List<Book> books;//作品
}
测试类
private static List<Author> getAuthors() {
//数据初始化
Author author = new Author(1L, "蒙多", 33, "一个从菜刀中明悟哲理的祖安人", null);
Author author2 = new Author(2L, "亚拉索", 15, "狂风也追逐不上他的思考速度", null);
Author author3 = new Author(3L, "易", 14, "是这个世界在限制他的思维", null);
Author author4 = new Author(3L, "易", 14, "是这个世界在限制他的思维", null);
//书籍列表
List<Book> books1 = new ArrayList<>();
List<Book> books2 = new ArrayList<>();
List<Book> books3 = new ArrayList<>();
books1.add(new Book(1L, "刀的两侧是光明与黑暗", "哲学,爱情",88,"用一把刀划分了爱恨"));
books1.add(new Book(2L,"一个人不能死在同一把刀下" , "个人成长,爱情" ,99, "讲述如何从失败中明悟真理"));
books2.add(new Book(3L, "那风吹不到的地方", "哲学" ,85, "带你用思维去领略世界的尽头"));
books2.add(new Book(3L, "那风吹不到的地方", "哲学" ,85, "带你用思维去领略世界的尽头"));
books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));
books3.add(new Book(5L, "你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));
books3.add(new Book(6L, "风与剑","个人传记",100, "两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
books3.add(new Book(6L, "风与剑","个人传记",100, "两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));
author.setBooks(books1);
author2.setBooks(books2);
author3.setBooks(books3);
author4.setBooks(books3);
ArrayList<Author> authorList = new ArrayList<>(Arrays.asList(author, author2, author3, author4));
return authorList;
}
问题:去重并打印18岁以下的名字
public static void main(String[] args) {
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.filter((author -> author.getAge()<18))
.forEach(author -> System.out.println(author.getName()));
}
创建流
单列集合:集合对象.stream()
Stream<Author> stream = list.stream();
数组:Arrays.stream(数组) 或者使用Stream.of来创建
Integer[] arr = {1,2,3,4,5};
//方法一
Stream<Integer> stream1 = Arrays.stream(arr);
//方法二
Stream<Integer> stream2 = Stream.of(arr);
双列集合:转换成单列集合在创建
public static void main(String[] args) {
HashMap<String, Integer> hashMap = new HashMap<>();
hashMap.put("小明",11);
hashMap.put("小红",11);
hashMap.put("小张",12);
Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();
Stream<Map.Entry<String, Integer>> stream = entries.stream();
stream.distinct()
.filter(entry -> entry.getValue() >11)
.forEach(System.out::println);
}
中间操作
filter
可以对流中的元素进行条件过滤,符合过滤条件的才能继续留在流中。
例如:
打印所有姓名长度大于1的作家的姓名
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.filter((author -> author.getName().length() > 1))
.forEach(author -> System.out.println(author.getName()));
map
可以把流中的元素进行计算或转换
例如:
//打印所有作家的姓名
List<Author> authors = getAuthors();
authors.stream()
.map(author -> {
author.setName("张三");
return author;//是将对象的name都改成 张三 但是还是返回的List对象
})
.map(author -> author.getName())//但是这里就相当于 将原来传入的List<Author> 变为List<String>
.forEach(name -> System.out.println(name instanceof String));//将括号中的换成name会全部打印张三
distinct
可以取出流中的重复元素
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.forEach(author -> System.out.println(author.getName()));
结果:
注意: distinct方法是依赖Object的equals方法来判断是否是相同对象的。所以需要注意重写equals方法。如果不重写就相当于== ,对象就是比较的地址值。
sorted
这个方法有两种形式:
① 如果调用空参的sorted()方法,需要流中的元素实现Comparable,并且重写compareTo方法
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode //用于后期的去重使用
public class Author implements Comparable<Author>{
private Long id;//id
private String name;//姓名
private Integer age;//年龄
private String intro;//简介
private List<Book> books;//作品
@Override
public int compareTo(Author o) {
return this.getAge() - o.getAge();
}
}
private static void test03() {
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.sorted()
.forEach(author -> System.out.println(author.getAge()));
}
② 带参数的sorted我们用的比较多
private static void test03() {
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.sorted((o1,o2)->o1.getAge()-o2.getAge())
.forEach(author -> System.out.println(author.getAge()));
}
结果:
limit
跟mysql中limit一个意思,一般配合sorted使用
例如:
打印年龄最大的两个作家并且去重
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.sorted((o1,o2)->o2.getAge()-o1.getAge())
.limit(2)
.forEach(author -> System.out.println(author.getName()));
结果:
skip
跳过前n个元素
例如:
打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。
private static void test04() {
List<Author> authors = getAuthors();
authors.stream()
.distinct()
.sorted((o1,o2)->o2.getAge()-o1.getAge())
.skip(1)
.forEach(author -> System.out.println(author.getName()));
}
结果:
flatMap
map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。
例如:
打印所有书籍的名字。要求对重复的元素进行去重
List<Author> authors = getAuthors();
authors.stream()
.flatMap(author -> author.getBooks().stream())
.distinct()
.forEach(book -> System.out.println(book.getName()));
结果:
//打印现有数据的所有分类。要求对分类进行去重。不能出现这种格式:哲学,爱情
List<Author> authors = getAuthors();
authors.stream()
.flatMap(author -> author.getBooks().stream())
.distinct()
.flatMap(book -> Arrays.stream(book.getCategory().split(",")))
.distinct()
.forEach(category -> System.out.println(category));
结果:
map和flatmap 的区别
map:map方法返回的是一个object,map将流中的当前元素替换为此返回值;
flatMap:flatMap方法返回的是一个stream,flatMap将流中的当前元素替换为此返回流拆解的流元素;
网上有一个比较经典的例子
有二箱鸡蛋,每箱5个,现在要把鸡蛋加工成煎蛋,然后分给学生。
map做的事情:把二箱鸡蛋分别加工成煎蛋,还是放成原来的两箱,分给2组学生;
flatMap做的事情:把二箱鸡蛋分别加工成煎蛋,然后放到一起【10个煎蛋】,分给10个学生;
说白了map 只是改变了原来流中元素的类型(即我们的返回值),而flatmap 是将原来流中的每个值都换成另一个流,然后把所有流连接成一个新的流,这是我的理解
终结操作
forEach
对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。
例如:
输出所有的作家的名字
List<Author> authors = getAuthors();
authors.stream()
.map(author -> author.getName())
.distinct()
.forEach(name -> System.out.println(name));
count
获取流中元素的个数
例如:
打印这些作家的所出书籍的数目,注意删除重复元素。
List<Author> authors = getAuthors();
long count = authors.stream()
.flatMap(author -> author.getBooks().stream())
.distinct()
.count();
System.out.println(count);
max&min
求流中的最大最小值
例如:
分别获取这些作家的所出书籍的最高分和最低分并打印。
List<Author> authors = getAuthors();
Optional<Integer> maxScore = authors.stream()
.flatMap(author -> author.getBooks().stream())
.map(score -> score.getScore())
.max((o1, o2) -> o1 - o2);//这里要实现Comparator的因为他不知道我们最大最小的规则是什么
System.out.println(maxScore.get());
collect
把当前流转换成一个集合
获取一个存放所有作者名字的List集合。
获取一个所有书名的set集合。
获取一个Map集合,map的key为作者名,value为List