ava 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
先创建测试对象
package com.example.springboot.Entity;
import lombok.*;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Author implements Comparable<Author>{
private int id;
private String name;
private int age;
/**
* 书籍列表
*/
private List<Book> bookList;
public static List<Author> getAuthers() {
Author a1 = Author.builder().id(1).name("张三").age(20).build();
Book b1 = Book.builder().id(100).name("倾城之恋").build();
Book b2 = Book.builder().id(200).name("挪威的森林").build();
List<Book> list1 = new ArrayList<Book>(){};
list1.add(b1);
list1.add(b2);
a1.setBookList(list1);
Author a2 = Author.builder().id(2).name("阿凡达").age(22).build();
Author a3 = Author.builder().id(3).name("李冰冰").age(33).build();
Author a4 = Author.builder().id(4).name("肉丝").age(34).build();
Book b3 = Book.builder().id(300).name("红楼梦").build();
List<Book> list3 = new ArrayList<Book>(){};
list3.add(b1);
list3.add(b3);
a3.setBookList(list3);
Author a5 = Author.builder().id(5).name("老刘").age(35).build();
Author a6 = Author.builder().id(6).name("大张").age(55).build();
List<Author> arrList = new ArrayList<>();
arrList.add(a1);
arrList.add(a2);
arrList.add(a3);
arrList.add(a4);
arrList.add(a5);
arrList.add(a6);
return arrList;
}
/**
* 自己实现Comparable接口
* @param o 排序对象
* @return 对比值
*/
@Override
public int compareTo(Author o) {
return o.getAge() - this.getAge();
}
/**
* 重写equals,ID一样就是相同数据
* @param obj 对比数据
* @return 是否为同一条数据
*/
public boolean equals(Object obj) {
//判断内存地址
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
//判断是否是同一类型的对象
if (obj instanceof Author) {
//强制转换成Person类型
Author per = (Author) obj;
//判断他们的属性值 注:这里的age为什么要用==?可以在评论区回答
if (this.id == per.id) {
return true;
}
}
return false;
}
}测试对象
package com.example.springboot.Entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private int id;
private String name;
/**
* 作者
*/
private int autId;
public static List<Book> getBookList(){
Book b1 = Book.builder().id(1).name("倾城之恋").autId(1).build();
Book b2 = Book.builder().id(2).name("荆棘鸟").autId(1).build();
Book b3 = Book.builder().id(3).name("挪威的森林").autId(2).build();
Book b4 = Book.builder().id(4).name("红楼梦").autId(3).build();
List<Book> arrList = new ArrayList<>();
arrList.add(b1);
arrList.add(b2);
arrList.add(b3);
arrList.add(b4);
return arrList;
}
/**
* 重写equals,ID一样就是相同数据
* @param obj 对比数据
* @return 是否为同一条数据
*/
public boolean equals(Object obj) {
//判断内存地址
if (obj == this) {
return true;
}
if (obj == null) {
return false;
}
//判断是否是同一类型的对象
if (obj instanceof Book) {
//强制转换成Person类型
Book per = (Book) obj;
//判断他们的属性值 注:这里的age为什么要用==?可以在评论区回答
if (this.id == per.id) {
return true;
}
}
return false;
}
}测试代码
package com.example.springboot;
import com.alibaba.fastjson.JSON;
import com.example.springboot.Entity.Author;
import com.example.springboot.Entity.Book;
import org.junit.jupiter.api.Test;
import java.util.*;
import java.util.stream.Collectors;
public class StreamTest {
/**
* findAny 随机 找到 一个 数据
* findFirst 找到 第一个 数据
*/
@Test
public void testFindAny(){
Optional<Author> optionalAuthor = Author.getAuthers().stream()
.distinct()
.filter(author -> author.getAge() >= 35)
.findFirst();
// .findAny();
optionalAuthor.ifPresent(author -> System.out.println(author));
}
/**
* anyMatch 流中数据是否有 一个 匹配数据
* allMatch 流中数据必须 全部 匹配
* noneMatch 流中数据 没有 匹配
*/
@Test
public void testMatch(){
boolean isHava = Author.getAuthers().stream()
.distinct()
.noneMatch(author -> author.getAge() >= 35);
// .allMatch(author -> author.getAge() >= 35);
// .anyMatch(author -> author.getAge() >= 35);
System.out.println("是否找到数据:" + isHava);
}
/**
* max 计算流中元素最大值,min类似
*/
@Test
public void testMax(){
Optional<Integer> max = Author.getAuthers().stream()
.distinct()
.map(author -> author.getAge())
// Idea会提示替换为下面写法
// .max((age1, age2) -> age1 - age2);
.max(Comparator.comparingInt(age -> age));
System.out.println(max.get());
}
/**
* count 统计流中元素个数
*/
@Test
public void testCount(){
long count = Author.getAuthers().stream()
.distinct()
.count();
System.out.println("共有数据:" + count);
}
/**
* reduce 将流中数据按照规则计算出一个结果
*/
@Test
public void testReduce(){
int re = Author.getAuthers().stream()
.distinct()
.map(author -> author.getAge())
// 计算作者年龄 总和,参数0是初始值
.reduce(0, (age1, age2) -> age1 + age2);
System.out.println("年龄总和:" + re);
re = Author.getAuthers().stream()
.distinct()
.map(author -> author.getAge())
// 计算作者年龄 最大,参数0是初始值
.reduce(0, (age1, age2) -> age1 > age2 ? age1 : age2);
System.out.println("年龄最大:" + re);
Optional<Integer> optionalInteger = Author.getAuthers().stream()
.distinct()
.map(author -> author.getAge())
// 计算作者年龄 最小,一个参数没有初始值
.reduce((age1, age2) -> age1 > age2 ? age2 : age1);
System.out.println("年龄最小:" + optionalInteger.get());
}
/**
* sorted 将流中数据按照规则排序
*/
@Test
public void testSorted(){
Author.getAuthers().stream()
// 使用对象实现的compareTo方法
// .sorted()
// 使用Lambda编写逻辑
// .sorted((aut1, aut2) -> aut1.getAge() - aut2.getAge())
// 使用提供的工具,reversed()降序
.sorted(Comparator.comparingInt(Author::getAge).reversed())
// 跳过一个后取前三个
.skip(1)
.limit(3)
.forEach(author -> System.out.println(author));
}
/**
* collect 将流转换为一个Set
*/
@Test
public void testCollectToSet() {
Set<Author> authorsSet = Author.getAuthers().stream()
.collect(Collectors.toSet());
System.out.println(JSON.toJSONString(authorsSet, true));
}
/**
* collect 将流转换为一个Map
*/
@Test
public void testCollectToMap() {
Map<Integer, Author> autMap = Author.getAuthers().stream()
// 先去重,否则有重复对象时报错
.distinct()
// 这里指定以作者ID为Key,以作者对象为Value
.collect(Collectors.toMap(Author::getId, author -> author));
System.out.println(JSON.toJSONString(autMap, true));
// 如果按指定规则收集时,会有多个结果,就使用分组,指定分组规则
Map<Integer, List<Book>> bookMap = Book.getBookList().stream()
// 一个作者会写多本书
.collect(Collectors.groupingBy(Book::getAutId));
System.out.println(JSON.toJSONString(bookMap, true));
}
/**
* collect 将流转换为一个List
*/
@Test
public void testCollectToList() {
List<String> autNameList = Author.getAuthers().stream()
.map(author -> author.getName())
.collect(Collectors.toList());
System.out.println(JSON.toJSONString(autNameList));
}
/**
* flatMap 返回流,该流将包含通过映射函数替换源流的每个元素而获得的元素,并展平结果
* distinct 通过equals方法判断是否为同一个对象,所以,可以重写Object的方法来定制
*/
@Test
public void testFlatMap() {
Author.getAuthers().stream()
// 注意这里依然要做为空判断
.flatMap(author -> null == author.getBookList() ? null : author.getBookList().stream())
.distinct()
.forEach(book -> System.out.println(book));
}
/**
* map 将流中对象进行转换
*/
@Test
public void testMap() {
Author.getAuthers().stream()
// 这里Map操作后返回的流里面都是String
.map(author -> author.getName())
.forEach(name -> System.out.println(name));
}
/**
* filter 过滤流中数据
*/
@Test
public void testFilter() {
Author.getAuthers().stream()
// 可以添加多个过滤条件
.filter(author -> author.getAge() >= 35)
.filter(author -> author.getName().length() >= 2)
.forEach(author -> System.out.println(author));
}
/**
* forEach 遍历流中数据
*/
@Test
public void testForEach() {
Author.getAuthers().stream()
.forEach(author -> System.out.println(author));
}
}
END
Java小强
未曾清贫难成人,不经打击老天真。
自古英雄出炼狱,从来富贵入凡尘。
发表评论: