# 1.stream流的定义
Stream是数据渠道,用于操作数据源所生成的元素序列,它可以实现对集合的复杂操作,例如过滤、排序和映射等。
(1)集合是一种静态的数据结构,存储在内存中,而Stream是通过CPU来实现计算的(并不会存储数据)
(2)Stream不会改变源对象,而是返回**一个新的持有结果**的Stream(不可变)
(3)Stream流只能使用一次
# 2.stream流的使用
## 2.1 stream流的创建
````
@Test
public void testCreatingStream() {
//Stream流只能使用一次
//数组
String[] str = {"hello", "world"};
Arrays.stream(str).forEach(s -> System.out.println(s));
//单列集合
List<String> list = new ArrayList<>();
//数组转换成集合
Arrays.asList(str);
}
````
## 2.2 stream流过滤filter
````
/**
* stream流过滤
*/
@Test
public void testFilter() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
//过滤年龄少于18岁的 使用stream流不用影响原list,使用collect收集器进行收集查找效果
List<User> collect = users.stream().filter(new Predicate<User>() {
@Override
public boolean test(User user) {
return user.getAge() >= 18;
}
}).collect(Collectors.toList());
//使用stream流不用影响原list
users.stream().forEach(user -> System.out.println(user));
System.out.println("----------------------------------------------");
collect.stream().forEach(user -> System.out.println(user));
}
````
源码中关于filter的说明
````
/**
* Returns a stream consisting of the elements of this stream that match
* the given predicate.
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to each element to determine if it
* should be included
* @return the new stream
*/
Stream<T> filter(Predicate<? super T> predicate);
````
User实体类
````
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private String id;
private String name;
private Integer age;
private String gender;
private Integer score;
private Date dob;
}
````
## 2.3 stream流中的映射之list转换成map
````
/**
* stream流list转换Map
* https://blog.youkuaiyun.com/qq_50523945/article/details/134989111
*/
@Test
public void testMap() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
//以用户ID作为key,user作为value
Map<String, User> collect1 = users.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));
User id0001User = collect1.get("id001");
System.out.println(id0001User);
System.out.println("-----------------------------------------");
collect1.forEach(new BiConsumer<String, User>() {
@Override
public void accept(String s, User user) {
System.out.println(collect1.get(s));
}
});
Map<String, String> collect2 = users.stream().collect(Collectors.toMap(User::getId, User::getName, (key1, key2) -> key2));
String id005Name = collect2.get("id005");
System.out.println("----------------------------------------");
System.out.println(id005Name);
}
````
## 2.4 stream流的分组groupBy
````
/**
* stream流分组(根据年龄)
*/
@Test
public void testGroupBy() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
Map<Integer, List<User>> collect = users.stream().collect(Collectors.groupingBy(User::getAge));
//根据年龄进行分组
collect.forEach(new BiConsumer<Integer, List<User>>() {
@Override
public void accept(Integer age, List<User> users) {
System.out.println(collect.get(age));
}
});
}
````
根据指定的日期格式进行分组groupby
````
/**
* stream流分组(根据出生日期年月分组)
*/
@Test
public void testGroupByDateFormat() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
Map<String, List<User>> collect = users.stream().collect(Collectors.groupingBy(user -> new SimpleDateFormat("yyyy-MM").format(user.getDob())));
//根据年龄进行分组
collect.forEach(new BiConsumer<String, List<User>>() {
@Override
public void accept(String yyyyMM, List<User> users) {
System.out.println(collect.get(yyyyMM));
}
});
}
````
## 2.5 stream流排序的使用sorted
````
/**
* stream流排序(根据年龄,成绩)
*/
@Test
public void testSort() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).score(100).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).score(98).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).score(88).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).score(98).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).score(88).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).score(100).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).score(96).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).score(100).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).score(100).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).score(90).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
//根据年龄从小到大排序
List<User> collect1 = users.stream().sorted(Comparator.comparing(User::getAge))
.collect(Collectors.toList());
collect1.forEach(user -> System.out.println(user));
System.out.println("-----------------------------------------------------------------");
//根据年龄从大到小排序
List<User> collect2 = users.stream().sorted(Comparator.comparing(User::getAge).reversed())
.collect(Collectors.toList());
collect2.forEach(user -> System.out.println(user));
System.out.println("-----------------------------------------------------------------");
//现根据年龄排序从大到小排序 如果年龄相同根据分数从高到低排序
List<User> collect3 = users.stream().sorted(Comparator.comparing(User::getAge)
.reversed()
.thenComparing(Comparator.comparing(User::getScore).reversed())
).collect(Collectors.toList());
collect3.stream().forEach(user -> System.out.println(user));
}
````
## 2.6 stream流聚合取值reduce
````
/**
* stream流的聚合取值
*/
@Test
public void testReduce() {
//求和
List<Integer> list = Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9});
Integer sum = list.stream().reduce((num1, num2) -> num1 + num2).get();
System.out.println(sum);
System.out.println("-------------------------------------");
//求最小值
Integer min = list.stream().reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer num1, Integer num2) {
if (num1 >= num2) {
return num2;
} else {
return num1;
}
}
}).get();
System.out.println(min);
}
````
## 2.7 Stream流的分页
````
/***
* stream流分页
*/
@Test
public void testPage() throws ParseException {
List<User> users = new ArrayList<User>(10);
User user1 = new User().builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23", YYYY_MM_DD)).build();
User user2 = new User().builder().id("id002").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23", YYYY_MM_DD)).build();
User user3 = new User().builder().id("id003").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11", YYYY_MM_DD)).build();
User user4 = new User().builder().id("id004").name("沙皇").age(17).gender("1").dob(DateUtils.parseDate("2005-01-18", YYYY_MM_DD)).build();
User user5 = new User().builder().id("id005").name("妖姬").age(24).gender("0").dob(DateUtils.parseDate("1998-01-18", YYYY_MM_DD)).build();
User user6 = new User().builder().id("id006").name("剑魔").age(18).gender("1").dob(DateUtils.parseDate("2004-10-23", YYYY_MM_DD)).build();
User user7 = new User().builder().id("id007").name("猫咪").age(18).gender("0").dob(DateUtils.parseDate("2004-06-23", YYYY_MM_DD)).build();
User user8 = new User().builder().id("id008").name("青刚影").age(20).gender("0").dob(DateUtils.parseDate("2002-10-23", YYYY_MM_DD)).build();
User user9 = new User().builder().id("id009").name("盲僧").age(24).gender("1").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
User user10 = new User().builder().id("id010").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23", YYYY_MM_DD)).build();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
users.add(user8);
users.add(user9);
users.add(user10);
List<User> page = users.stream().skip(0).limit(5).collect(Collectors.toList());
System.out.println(users.size());
System.out.println(page.size());
page.stream().forEach(user -> System.out.println(user));
}
````
## 2.8 stream流的匹配match
````
/***
* stream流的匹配
*/
@Test
public void testMatch() {
List<ClassA> aList = new ArrayList<>(Arrays.asList(
new ClassA("1", "张三"),
new ClassA("2", "李四"),
new ClassA("3", "王五")
));
List<ClassB> bList = new ArrayList<>(Arrays.asList(
new ClassB("2", "李某"),
new ClassB("3", "王某"),
new ClassB("4", "赵某")
));
//aList与bList的交集
List<ClassA> intersectA = aList
.stream() //获取第一个集合的Stream1
.filter( //取出Stream1中符合条件的元素组成新的Stream2,lambda表达式1返回值为true时为符合条件
a -> //lambda表达式1,a为lambda表达式1的参数,是Stream1中的每个元素
bList.stream() //获取第二个集合的Stream3
.map(ClassB::getId) //将第二个集合每个元素的id属性取出来,映射成新的一个Stream4
.anyMatch( //返回值(boolean):Stream4中是否至少有一个元素使lambda表达式2返回值为true
id -> //lambda表达式2,id为lambda表达式2的参数,是Stream4中的每个元素
Objects.equals(a.getId(), id) //判断id的值是否相等
)
)
.collect(Collectors.toList()); //将Stream2转换为List
System.out.println(intersectA);
//bList与aList的差集
List<ClassB> differenceB = bList.stream().filter(b -> aList.stream().map(ClassA::getId).noneMatch(id -> Objects.equals(b.getId(), id))).collect(Collectors.toList());
System.out.println(differenceB);
//aList与bList的差集
List<ClassA> differenceA = aList.stream().filter(a -> bList.stream().map(ClassB::getId).noneMatch(id -> Objects.equals(a.getId(), id))).collect(Collectors.toList());
System.out.println(differenceA);
}
class ClassA {
String id;
String realName;
public ClassA(String id, String realName) {
this.id = id;
this.realName = realName;
}
@Override
public String toString() {
return "ClassA{" +
"id='" + id + ''' +
", realName='" + realName + ''' +
'}';
}
public String getId() {
return id;
}
public String getRealName() {
return realName;
}
}
class ClassB {
String id;
String nickName;
public ClassB(String id, String nickName) {
this.id = id;
this.nickName = nickName;
}
@Override
public String toString() {
return "ClassB{" +
"id='" + id + ''' +
", nickName='" + nickName + ''' +
'}';
}
public String getId() {
return id;
}
public String getNickName() {
return nickName;
}
}
````
## 2.9 stream流map根据value进行分组
````
/***
* map集合根据value进行分组
*/
@Test
public void testMapGroupByValue(){
Map<String, String> map = new HashMap<>();
Map<String, Set<String>> groupMap = new HashMap<>();
map.put(null, null);
map.put(null, null);
map.put("c", null);
map.put("c", "3");
map.put("e", "4");
map.put("f", "5");
map.put("G", "4");
map.put("h", "5");
//根据value分组之前
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
System.out.println(key+"->"+value);
}
});
System.out.println("----------------------------------------------------");
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
if (groupMap.containsKey(value)) {
groupMap.get(value).add(key);
} else {
Set<String> values = new HashSet<>();
values.add(key);
groupMap.put(value, values);
}
}
});
//根据value分组之后
groupMap.forEach(new BiConsumer<String, Set<String>>() {
@Override
public void accept(String value, Set<String> keys ) {
System.out.println(value+"->"+keys);
}
});
}
````
## 2.10 stream流map根据指定出生日期进行分组,分组的组内数据再根据时间从最新往下排列
```js
@Test
public void testMain() throws ParseException {
User user1 = User.builder().id("id001").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23 10:23:00", YYYY_MM_DD_HH_MM_SS)).build();
User user2 = User.builder().id("id002").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23 18:23:00", YYYY_MM_DD_HH_MM_SS)).build();
User user3 = User.builder().id("id003").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23 19:23:00", YYYY_MM_DD_HH_MM_SS)).build();
User user4 = User.builder().id("id004").name("船长").age(23).gender("1").dob(DateUtils.parseDate("1999-10-23 16:23:00", YYYY_MM_DD_HH_MM_SS)).build();
User user5 = User.builder().id("id005").name("阿卡丽").age(16).gender("0").dob(DateUtils.parseDate("2006-10-23 00:00:00", YYYY_MM_DD_HH_MM_SS)).build();
User user6 = User.builder().id("id006").name("凯南").age(16).gender("1").dob(DateUtils.parseDate("2006-11-11 00:00:00", YYYY_MM_DD_HH_MM_SS)).build();
User user7 = User.builder().id("id007").name("露露").age(24).gender("0").dob(DateUtils.parseDate("1998-10-23 00:00:00", YYYY_MM_DD_HH_MM_SS)).build();
List<User> users = new ArrayList<>();
users.add(user1);
users.add(user2);
users.add(user3);
users.add(user4);
users.add(user5);
users.add(user6);
users.add(user7);
Map<String, List<User>> collect = users.stream().collect(Collectors.groupingBy(user -> new SimpleDateFormat("yyyy-MM-dd").format(user.getDob())));
Set<String> strings = collect.keySet();
List<String> sortedKeys = strings.stream().sorted(new Comparator<String>() {
@SneakyThrows
@Override
public int compare(String o1, String o2) {
Date date1 = DateUtils.parseDate(o1, YYYY_MM_DD);
Date date2 = DateUtils.parseDate(o2, YYYY_MM_DD);
if (date1.getTime() < date2.getTime()) {
return 1;
} else {
return -1;
}
}
}).collect(Collectors.toList());
Map<String, List<User>> map = new LinkedHashMap<>();
for (String sortedKey : sortedKeys) {
List<User> tempList = collect.get(sortedKey);
List<User> newList = tempList.stream().sorted(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
if (o1.getDob().getTime() < o2.getDob().getTime()) {
return 1;
} else {
return -1;
}
}
}).collect(Collectors.toList());
map.put(sortedKey,newList);
}
Set<String> keys = map.keySet();
for (String key : keys) {
System.out.println(key+"-->"+map.get(key));
}
}
```