1.当接口中的方法只有一个参数时,可以省略类型与小括号
2.如果只有一个return,直接省略;
3.只有一句话省略分号和括号
1.Stream流->对集合进行操作
2.将数据按照流的形式进行链式的操作——>方便对集合和数组操作
3.对参数alter enter可以重新匿名内部类
4.流中的每一个方法的调用类似于工厂的一个组件,每个组件的完成需要终结方法的调用
终结方法:eg:foreach()
1.双列集合类似Map这种需要先转为单列结合entrySet,再转为Stream流
2.map:将元素转为map形式,并且能够对元素进行计算重写
3.disnect去重本质用的equals方法进行元素判断重写
1.sorted会将元素类型转为comparable
文档:
返回由该流的元素组成的流,按自然顺序排序。如果该流的元素不是
{@code Comparable},则在执行终端操作时可能会抛出 {@code java.lang.ClassCastException}。
<p>对于有序流,排序是稳定的。对于无序流,不保证稳定性。
<p>这是一个<a href="package-summary.htmlStreamOps">有状态的中间操作<a>。 @return 新的流
2.解决:
implements Comparable<Author>
3.例子:
@Override
public int compareTo(Author o) {
//传入的-本地的,降序
return o.getAge()-this.getAge();
}
我们还可以sorted中时间Comparator接口进行重写compare方法
1.skip(n):将流中前n个元素去除
1.flatMap:可以将元素套娃,将流中的元素类型进行改变 xxx->xxx.xx.stream()
场景:比如得到作者中的书籍,得到书籍中的所属类型
2.count:求流中的元素个数
1.max():获取流元素中的最大值
min():获取流元素最小值,具体可以实现comparator接口
2.collect():将信息变为指定类型
实现Collections.ToMap(xx,xx):里面两个参数对应的map的key与value
1.anyMatch():与filter()意思相近,但是它是可以返回值的,filter只是起到一个过滤的逻辑
allMatch():判断流中所有元素是否满足要求
1.findAnyWay():获取流元素,返回Optional,可以对里面流元素进行操作
比如:ifPresent()->根据判断执行逻辑...
2.findFirst():查找流中第一个元素
1.reduce():将stream流中的元素给组合起来,根据我们传入的初始值,按照我们自己的计算方式以此拿取流中的数据进行运算;
max和min的源代码就是基于reduce方法实现的
注意:
1.流是惰性的,终结操作后就没了(比如:foreach)——>可以根据目前状况重新创建一个流
1.Optional:可以帮助避免空指针异常
实际开发也可以用这个,在数据dao中返回Optional
2.如果确定返回一定不是null,也可以用Optional.of()
3.Optional.ofNullable():万能,是不是null都能封装
例子:
类似于->return author==null?Optional.empty():Optional.of(author);
4.OrElseThrow():如果有数据就返回数据,如果没数据就抛出异常
5.OrElseGet():判读是否为空,为空返回一个新的
例子:Optional<Author> author1 = author.orElseGet(() -> Optional.of(new Author()));
注意:Optional后续操作返回的对象都是一个新的Optional
比如: Optional<Author> optional = getAuthorOptional();
optional.filter(author -> author.getAge()>18)
//前面对流中元素进行过滤,后面进行判断看输出否
.ifPresent(author -> System.out.println("名字是:"+author.getName()));
6.Optional后续判断如果为null,那么后续操作就不会执行
7.Optional中的消息的安全消费可以使用ifPresent()
函数式接口
1.只有一个抽象方法的就是函数式接口@FunctionalInterface(只有一个方法)
这些就可以用lambda简化
2.Consumer:消费接口
3.Function:计算转换接口,我们可以吧传入的参数进行转换(比如转为list,map...)
例子:
authorList.stream()
//将元素转为map形式,值为String类型
.map(new Function<Author, String>() {
@Override
public String apply(Author author) {
return author.getName();
}
})
4.predicate 判断接口,一般用于过滤流中元素
我们可以在后面接and、or、negate进行多重判断,或判断,非判断
例子:authorList.stream()
.filter(((Predicate<Author>) author -> author.getName().length() > 9).or(author -> author.getAge()>19)).forEach(author -> System.out.println("被消费的作者名字为:"+author.getName()));
1.方法引用基本格式
authorList.stream()
.map(Author::getAge)
.map(age->age+10)
.forEach(age-> System.out.println("年龄为:"+age));
1.并行流:
其实就是把任务分配给多个线程执行
可以和线程池一起使用,但是结合代码我发现他可能自己是实现了一个线程池,所以结果出现了多个池的线程共享一个数据的情况
package com.wuyuhang.stream;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author diao 2022/6/21
*/
@Slf4j(topic = "c.StreamDemoTest")
public class StreamDemoTest {
public static void main(String[] args) {
List<Author> authorList = getAuthors();
test01(authorList);
testArrToStream();
testMapToStream();
testAuthor(authorList);
//元素转为map形式,对元素进行操作
valueToMapPrint(authorList);
//去重内部用的equals
JudgeToDisnect(authorList);
//排序无重复
sortAndDisnect(authorList);
//对流元素进行降序,无重复,打印年龄最大
limitAndDPrint(authorList);
//除去最大的其他元素:skip
skipMax(authorList);
//对书籍元素进行去重打印(每个作者的书籍)
authorBooks(authorList);
//打印所有作者的所有书籍(Book)flatMap
flatMapToBooks(authorList);
//打印所有书籍,flatMap优化版本
flatMapGBooks(authorList);
//得到书籍的所有类型进行去重打印
getCatagoryForStream(authorList);
testBooks(authorList);
//计算当前流中元素个数,删除重复元素
countStream(authorList);
/**
* 得到书籍的评分,需要将得到书籍评分的流元素(flatMap)
* 我们也可以得到书的流,然后得到书的评分,最后利用Comparator接口实现比较排序即可
*/
bookMaxStore(authorList);
//获取放入作者名字的List集合
AuthorNameToList(authorList);
/**
* 将作者信息转为map形式,键为名字,值为书籍
* 将Author->键设置为它的名字
*/
// authorToMap(authorList);
/**
* 判断是否有大盂29的作家
*/
anyMatch(authorList);
/**
* 全局判断
*/
allMatchToAuther(authorList);
/**
* 判断作家是不是都没有超过100岁
*/
nonmatchToAge(authorList);
/**
* findAny():对流中元素进行获取->返回Optional
* 根据Optional的api进行后续的消费操作
*/
findAny(authorList);
/**
* 排序并且打印排序的第一个数据
* (Optional)然后判断进行打印
*/
sortAndFirst(authorList);
/**
*reduce的使用
* 求所有作者的年龄的和
* 注意:需要对流中元素进行改变,因为目前是author,我们需要改为年龄
* 改完后reduce就可以实现Integer累加操作了
*/
reduceGetSum(authorList);
/**
* reduce求得作者年龄的最大值
*/
reduceGetMax(authorList);
/**
* 拿第一个元素作为初始值,将后面的元素进行运算
*/
reduceOneImport(authorList);
/**
* 测试是否会影响原数据
*/
zhongJie(authorList);
authorList.stream()
.map(Author::getAge)
.map(age -> age + 10)
.forEach(age -> System.out.println("年龄为:" + age));
/**
* 双重测试
*/
twoFilter(authorList);
/**
* 或者测试
*/
orTest(authorList);
/**
* 并行流
*/
threadPool.submit(new Runnable() {
@Override
public void run() {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
//将流转为并行流
Optional<Integer> reduce = stream.parallel()
.peek(num -> {
//Consumer消费打印当前线程名字
System.out.println(num + Thread.currentThread().getName());
})
.filter(integer -> integer > 5)
.reduce((result, element) -> result + element);
System.out.println("最后总结果为:" + reduce);
}
});
System.out.println("================");
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9);
//将流转为并行流
Optional<Integer> reduce = stream.parallel()
.peek(num -> {
//Consumer消费打印当前线程名字
System.out.println(num + Thread.currentThread().getName());
})
.filter(integer -> integer > 5)
.reduce((result, element) -> result + element);
System.out.println("最后总结果为:" + reduce);
}
private static void orTest(List<Author> authorList) {
authorList.stream()
.filter(((Predicate<Author>) author -> author.getName().length() > 9).or(author -> author.getAge() > 19)).forEach(author -> System.out.println("被消费的作者名字为:" + author.getName()));
}
private static void twoFilter(List<Author> authorList) {
authorList.stream()
.filter(new Predicate<Author>() {
@Override
public boolean test(Author author) {
return author.getAge() > 17;
}
//双重判断
}.and(new Predicate<Author>() {
@Override
public boolean test(Author author) {
return author.getName().length() > 1;
}
})).forEach(author -> System.out.println(author.getAge() + "名字:" + author.getName()));
}
private static void zhongJie(List<Author> authorList) {
authorList.stream()
.map(author -> author.getAge())
.map(ag -> ag + 10)
.forEach(ag -> System.out.println(ag));
}
private static void reduceOneImport(List<Author> authorList) {
authorList.stream()
.map(author -> author.getAge())
//第一个初始值为流中的一个元素,也就是默认的result
.reduce((result, element) -> {
//取最小值
return result > element ? element : result;
})
.ifPresent(age -> System.out.println("最小年龄存在,为:" + age));
}
private static void reduceGetMax(List<Author> authorList) {
authorList.stream()
.map(author -> author.getAge())
.distinct()
.reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer result, Integer element) {
//用三元运算符求得元素中的最大值
return result < element ? result : result;
}
});
}
private static void reduceGetSum(List<Author> authorList) {
Integer sum = authorList.stream()
//将stream流元素变为年龄
.map(author -> author.getAge())
.distinct()
//element为流中的元素
.reduce(0, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer result, Integer element) {
return result + element;
}
});
System.out.println("年龄之和为:" + sum);
}
private static void sortAndFirst(List<Author> authorList) {
Optional<Author> first = authorList.stream()
//进行排序
.sorted((o1, o2) -> o1.getAge() - o2.getAge())
//取到排序中的第一个数据
.findFirst();
//对Optional数据进行判断
first.ifPresent(author -> System.out.println("输出第一个作者:" + author.getName()));
}
private static void findAny(List<Author> authorList) {
Optional<Author> optionalAuthor = authorList.stream()
//filter过滤判断一些元素(>18的就保存在流中)
.filter(author -> author.getAge() > 18)
.findAny();
//进行判断(Optional调用这个api)
//如果存在这个数据就会执行这个消费的操作
optionalAuthor.ifPresent(author -> System.out.println(author.getName()));
}
private static void nonmatchToAge(List<Author> authorList) {
boolean match = authorList.stream()
.noneMatch(author -> author.getAge() > 100);
System.out.println("是否满足:" + match);
}
private static void allMatchToAuther(List<Author> authorList) {
boolean flag = authorList.stream()
//对流中元素,对元素年龄进行判断
.allMatch(author -> author.getAge() >= 18);
System.out.println(flag);
}
private static void anyMatch(List<Author> authorList) {
boolean match = authorList.stream()
//filter不是终结操作,没有返回值
.anyMatch(author -> author.getAge() > 29);
System.out.println("是否满足:" + match);
boolean match1 = authorList.stream()
.anyMatch(author -> author.getAge() > 36);
System.out.println(match1);
}
// private static void authorToMap(List<Author> authorList) {
// authorList.stream()
// .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));
// }
private static void AuthorNameToList(List<Author> authorList) {
List<String> collect = authorList.stream()
//将author的名字放入map集合中做元素
.map(author -> author.getName())
//转为list集合
.collect(Collectors.toList());
System.out.println("collect集合中元素为:" + collect);
}
private static void bookMaxStore(List<Author> authorList) {
Optional<Integer> max = authorList.stream()
//得到书流元素
.flatMap(author -> author.getBooks().stream())
//map中为流元素(book)的评分
.map(book -> {
return book.getScore();//得到book的评分
})
//再做一个比较器,将评分比较
.max((o1, o2) -> o1 - o2);
System.out.println("得到最大的评分:" + max);
}
private static void countStream(List<Author> authorList) {
long count = authorList.stream()
//将作者的书籍平展开来作为流元素,然后去重书籍
.flatMap(author -> author.getBooks().stream())
.distinct()
.count();
System.out.println("书籍数量是:" + count);
}
private static void testBooks(List<Author> authorList) {
authorList.stream()
.map(author -> author.getBooks())
.distinct()
.forEach(books -> System.out.println("作者的书籍为:" + books));
}
private static void getCatagoryForStream(List<Author> authorList) {
authorList.stream()
.flatMap(author -> author.getBooks().stream())
.distinct()
//此时流元素中是book,我们得到book中而书籍类型拿出来(也就是一个数组),然后将书籍类型种族安慰流元素
.flatMap(book -> Arrays.stream(book.getCategory().split(",")))
.distinct()
.forEach(s -> System.out.println("类型为:" + s));
}
private static void flatMapGBooks(List<Author> authorList) {
authorList.stream()
//将流元素进行平展
.flatMap(author -> author.getBooks().stream())
.distinct()
.forEach(book -> System.out.println("优化后书籍为:" + book));
}
private static void authorBooks(List<Author> authorList) {
authorList.stream()
//得到每个作者的所有书籍,所以map中的每个元素都是书籍
.map(new Function<Author, List<Book>>() {
@Override
public List<Book> apply(Author author) {
return author.getBooks();
}
})
.distinct()
.forEach(books -> System.out.println("作者书籍为:" + books));
}
private static void flatMapToBooks(List<Author> authorList) {
authorList.stream()
//flatmap:对多个流进行合并处理
.flatMap((Function<Author, Stream<Book>>) author -> {
//书全被合在一起
return author.getBooks().stream();
})
.distinct()
.forEach(book -> System.out.println("书籍为:" + book));
}
private static void skipMax(List<Author> authorList) {
authorList.stream()
.distinct()
.sorted((o1, o2) -> o2.getAge() - o1.getAge())
.skip(1)
.forEach(author -> System.out.println(author));
}
private static void limitAndDPrint(List<Author> authorList) {
authorList.stream()
.distinct()
//降序年龄排序
.sorted((o1, o2) -> o1.getAge() - o2.getAge())
//两个最大元素
.limit(2)
.forEach(author -> System.out.println("最大的元素为:" + author));
}
private static void sortAndDisnect(List<Author> authorList) {
authorList.stream()
.distinct()
//o1是传入项
.sorted((o1, o2) -> o1.getAge() - o2.getAge())
.forEach(author -> System.out.println("排序后的作者:" + author));
}
private static void JudgeToDisnect(List<Author> authorList) {
authorList.stream()
//里面每个元素都会进行判断
.distinct()
.forEach(author -> System.out.println(author));
}
private static void valueToMapPrint(List<Author> authorList) {
authorList.stream()
//将元素转为map形式,值为String类型
.map(new Function<Author, String>() {
@Override
public String apply(Author author) {
return author.getName();
}
})
//map中元素进行遍历
.forEach(s -> System.out.println("转化后值为:" + s));
authorList.stream()
.map(new Function<Author, Integer>() {
@Override
public Integer apply(Author author) {
return author.getAge();
}
})
.forEach(s -> {
System.out.println("转化后值为:" + s);
});
//对元素进行重新计算
authorList.stream()
.map(author -> author.getAge() + 10)
.forEach(integer -> System.out.println(integer));
}
private static void testAuthor(List<Author> authorList) {
//中间操作
authorList.stream()
.filter(author -> author.getName().length() > 1)
.forEach(author -> System.out.println(author.getName()));
}
private static void testMapToStream() {
//map集合
HashMap<String, Integer> map = new HashMap<>();
map.put("蜡笔小新", 19);
map.put("Fairy同学", 17);
map.put("Stream流", 16);
// 先转为entrySet,目的是单列集合(键值对算一个,一个一个来)
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
//将entrySet转为Stream流
Stream<Map.Entry<String, Integer>> stream = entrySet.stream();
stream.filter(new Predicate<Map.Entry<String, Integer>>() {
@Override
public boolean test(Map.Entry<String, Integer> entry) {
return entry.getValue() > 16;
}
})
.forEach(entry -> System.out.println(entry.getKey() + "===" + entry.getValue()));
}
private static void testArrToStream() {
/**
* 数组转为Stream流
*/
Integer[] arr = {1, 2, 3, 5, 6};
Stream<Integer> stream = Arrays.stream(arr);
stream.distinct()
.filter(integer -> integer > 3)
.forEach(integer -> System.out.println(integer));
}
private static void test01(List<Author> authorList) {
/**
* 把集合转换为流
* 流进行操作,lambda进行简化
*/
//打印每一个作者名字
authorList.stream()
.distinct()
.filter(author -> {//把每一个作者传入进行过滤判断
return author.getAge() < 18;
})
.forEach(author -> System.out.println(author.getName()));
}
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);
//将所有作者作为一个集合
List<Author> authorList = new ArrayList<>(Arrays.asList(author, author2, author3, author4));
return authorList;
}
//自定义线程池
public static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 50, 300, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(50),
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "schema_task_pool_" + r.hashCode());
}
}, new ThreadPoolExecutor.DiscardOldestPolicy());
}