一、stream 介绍(抄录一波)
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
+--------------------+ +------+ +------+ +---+ +-------+ | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect| +--------------------+ +------+ +------+ +---+ +-------+
以上的流程转换为 Java 代码为:
List<Integer> transactionsIds = widgets.stream() .filter(b -> b.getColor() == RED) .sorted((x,y) -> x.getWeight() - y.getWeight()) .mapToInt(Widget::getWeight) .sum();
二、案列编写 动手写一遍或者运行一下基本就学会啦
1.创建案例需要使用的实体
public class User {
private String name;
private int salary;
private String address;
private int age;
private String sex;
private String province;
private String city;
private String area;
public User(String name, int salary, int age, String sex, String province, String city, String area) {
this.name = name;
this.salary = salary;
this.age = age;
this.sex = sex;
this.province = province;
this.city = city;
this.area = area;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", salary=" + salary +
", address='" + address + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
/**
* 判断两个对象是否相同 默认是判断对象的所有属性是否全部相同
* 重写单独属性equals和hashCode
* 只要此属性的值相同,则认为两个对象就是相同的
* @param o
* @return
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
2.foreach/find/match的用法
@SpringBootTest
class StreamApplicationTests {
List<User> initUserList(){
List<User> list = new ArrayList<>();
list.add(new User("xiaoHu", 150000, 24, "man","Henan","Zhengzhou","Erqi"));
list.add(new User("LetMe", 160000, 27, "man","Zhejiang","Hangzhou","Xihu"));
list.add(new User("Mlxg", 170000, 26, "man","Shandong","Jinan","Qianfoshan"));
list.add(new User("xiaoMing", 160000, 25, "man","Jiangsu","Nanjing","Yuhuatai"));
list.add(new User("Miss", 180000, 18, "women","Henan","Zhoukou","chuanhuiqu"));
list.add(new User("Uzi", 200000, 23, "man","Shandong","Qingdao","Laoshan"));
return list;
}
List<User> initUserList2(){
List<User> list = new ArrayList<>();
list.add(new User("xiaoHu", 150000, 24, "man","Henan","Zhengzhou","Erqi"));
list.add(new User("Gala", 160000, 27, "man","Zhejiang","Hangzhou","Xihu"));
list.add(new User("Wei", 170000, 26, "man","Shandong","Jinan","Qianfoshan"));
list.add(new User("xiaoMing", 160000, 25, "man","Jiangsu","Nanjing","Yuhuatai"));
list.add(new User("YuShuang", 180000, 18, "women","Henan","Zhoukou","chuanhuiqu"));
list.add(new User("Cryin", 200000, 23, "man","Shandong","Qingdao","Laoshan"));
return list;
}
@Test //(foreach/find/match)
void streamForeach() {
List<User> users = initUserList();
//队员薪资大于160000的打印出来信息
users.stream().filter(u->u.getSalary()>160000).forEach(System.out::println);
//队员薪资大于160000的第一个用户的信息
Optional<User> first = users.stream().filter(u -> u.getSalary() > 160000).findFirst();
//队员薪资大于160000的任意一个用户信息
Optional<User> any = users.stream().filter(u -> u.getSalary() > 160000).findAny();
System.out.println("薪资大于160000的第一个用户的信息" + first.get());
System.out.println("薪资大于160000的任意一个用户信息" + any.get());
}
}
输出结果
User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}
User{name='Miss', salary=180000, address='null', age=18, sex='women'}
User{name='Uzi', salary=200000, address='null', age=23, sex='man'}
薪资大于160000的第一个用户的信息User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}
薪资大于160000的任意一个用户信息User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}
3.筛选(filter) 并形成新的集合。形成新集合依赖collect
@Test //筛选(filter) 并形成新的集合。形成新集合依赖collect
void streamFilter(){
List<User> users = initUserList();
//队员年龄大于25岁的人的集合
Collection<User> collect = users.stream().filter(u -> u.getAge() > 25).collect(Collectors.toList());
System.out.println("队员年龄大于25岁的人的集合:"+collect);
}
输出:
队员年龄大于25岁的人的集合:[User{name='LetMe', salary=160000, address='null', age=27, sex='man'}, User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}]
4.映射map
@Test //映射map
void streamMap(){
List<User> users = initUserList();
//队员年龄大于25岁人的姓名的集合
List<String> collect = users.stream().filter(u -> u.getAge() > 25).map(User::getName).collect(Collectors.toList());
//将队员所有人名字改成大写
List<String> collect1 = users.stream().map(User::getName).map(String::toUpperCase).collect(Collectors.toList());
System.out.println("队员年龄大于25岁人的姓名的集合:"+collect);
System.out.println("将队员所有人名字改成大写"+collect1);
}
输出:
队员年龄大于25岁人的姓名的集合:[LetMe, Mlxg]
将队员所有人名字改成大写[XIAOHU, LETME, MLXG, XIAOMING, MISS, UZI]
5.归约(reduce)是把一个流缩减成一个值,能实现对集合求和等
@Test //归约(reduce)是把一个流缩减成一个值,能实现对集合求和等
void streamReduce(){
List<User> users = initUserList();
//队员所有人的薪资之和
Optional<Integer> reduce = users.stream().map(User::getSalary).reduce(Integer::sum);
System.out.println("队员所有人的薪资之和"+reduce.get());
//队员最高薪资
Optional<Integer> reduce1 = users.stream().map(User::getSalary).reduce(Integer::max);
System.out.println("队员最高薪资"+reduce1.get());
}
输出:
队员所有人的薪资之和1020000
队员最高薪资200000
6.collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合
@Test //collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合
void streamCollect() throws JsonProcessingException {
List<User> users = initUserList();
//队员是河南人的集合
List<User> heNan = users.stream().filter(u -> u.getProvince().equals("Henan")).collect(Collectors.toList());
System.out.println("队员是河南人的集合"+heNan);
//大于25岁的队员
Map<String, User> collect = users.stream().filter(x -> x.getAge() > 25).collect(Collectors.toMap(User::getName, p -> p));
String s = new ObjectMapper().writeValueAsString(collect);
System.out.println("大于21岁的队员"+s);
}
输出:
队员是河南人的集合[User{name='xiaoHu', salary=150000, address='null', age=24, sex='man'}, User{name='Miss', salary=180000, address='null', age=18, sex='women'}]
大于21岁的队员{"Mlxg":{"name":"Mlxg","salary":170000,"address":null,"age":26,"sex":"man","province":"Shandong","city":"Jinan","area":"Qianfoshan"},"LetMe":{"name":"LetMe","salary":160000,"address":null,"age":27,"sex":"man","province":"Zhejiang","city":"Hangzhou","area":"Xihu"}}
PS:ObjectMapper()对象是实现json的核心 当没有导入json依赖时 可以从这个类
7.统计
@Test //统计
void streamCount(){
//队员人数
List<User> users = initUserList();
long count = users.stream().count();
System.out.println("队员人数"+count);
//队员平均工资
Double collect = users.stream().collect(Collectors.averagingInt(u -> u.getSalary()));
Double collect1 = users.stream().collect(Collectors.averagingDouble(User::getSalary));
System.out.println("队员平均工资"+collect+"====队员平均工资"+collect1);
//队员最大薪资
Optional<Integer> collect2 = users.stream().map(User::getSalary).collect(Collectors.maxBy(Integer::compare));
System.out.println("队员最大薪资"+collect2.get());
}
输出:
队员人数6
队员平均工资170000.0====队员平均工资170000.0
队员最大薪资200000
8.分组
public void streamGroup() throws JsonProcessingException {
List<User> users = initUserList();
// 将队员按省份分组
Map<String, List<User>> collect = users.stream().collect(Collectors.groupingBy(User::getProvince));
System.out.println(collect);
// 将队员按省份分组 再按性别分组
Map<String, Map<String, List<User>>> collect1 = users.stream().collect(Collectors.groupingBy(User::getProvince, Collectors.groupingBy(User::getSex)));
String s = new ObjectMapper().writeValueAsString(collect1);
System.out.println(s);
}
输出:
{Zhejiang=[User{name='LetMe', salary=160000, address='null', age=27, sex='man'}], Henan=[User{name='xiaoHu', salary=150000, address='null', age=24, sex='man'}, User{name='Miss', salary=180000, address='null', age=18, sex='women'}], Jiangsu=[User{name='xiaoMing', salary=160000, address='null', age=25, sex='man'}], Shandong=[User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}, User{name='Uzi', salary=200000, address='null', age=23, sex='man'}]}
{"Zhejiang":{"man":[{"name":"LetMe","salary":160000,"address":null,"age":27,"sex":"man","province":"Zhejiang","city":"Hangzhou","area":"Xihu"}]},"Henan":{"man":[{"name":"xiaoHu","salary":150000,"address":null,"age":24,"sex":"man","province":"Henan","city":"Zhengzhou","area":"Erqi"}],"women":[{"name":"Miss","salary":180000,"address":null,"age":18,"sex":"women","province":"Henan","city":"Zhoukou","area":"chuanhuiqu"}]},"Jiangsu":{"man":[{"name":"xiaoMing","salary":160000,"address":null,"age":25,"sex":"man","province":"Jiangsu","city":"Nanjing","area":"Yuhuatai"}]},"Shandong":{"man":[{"name":"Mlxg","salary":170000,"address":null,"age":26,"sex":"man","province":"Shandong","city":"Jinan","area":"Qianfoshan"},{"name":"Uzi","salary":200000,"address":null,"age":23,"sex":"man","province":"Shandong","city":"Qingdao","area":"Laoshan"}]}}
9.joining
@Test //joining 将每个队员的名字连接起来
public void streamJoining(){
List<User> users = initUserList();
//将每个队员的名字连接起来
String collect = users.stream().map(User::getName).collect(Collectors.joining("-"));
System.out.println("将每个队员的名字连接起来"+collect);
}
输出:
将每个队员的名字连接起来xiaoHu-LetMe-Mlxg-xiaoMing-Miss-Uzi
10.sort排序
@Test//sort
void streamSorted(){
List<User> users = initUserList();
//工资由低到高
List<User> collect = users.stream().sorted(Comparator.comparing(User::getSalary)).collect(Collectors.toList());
//工资由低到高 工资相等时 再按年龄由低到高
List<String> collect1 = users.stream().sorted(Comparator.comparing(User::getSalary).reversed().thenComparing(User::getAge)).map(User::getName).collect(Collectors.toList());
System.out.println("工资由低到高:"+collect);
System.out.println("工资由低到高 工资相等时 再按年龄由低到高"+collect1);
}
输出:
工资由低到高:[User{name='xiaoHu', salary=150000, address='null', age=24, sex='man'}, User{name='LetMe', salary=160000, address='null', age=27, sex='man'}, User{name='xiaoMing', salary=160000, address='null', age=25, sex='man'}, User{name='Mlxg', salary=170000, address='null', age=26, sex='man'}, User{name='Miss', salary=180000, address='null', age=18, sex='women'}, User{name='Uzi', salary=200000, address='null', age=23, sex='man'}]
工资由低到高 工资相等时 再按年龄由低到高[Uzi, Miss, Mlxg, xiaoMing, LetMe, xiaoHu]
10.distinct limit skip
@Test//distinct limit skip
void streamDistinct(){
List<User> users = initUserList();
List<User> users1 = initUserList2();
//两个队队员的总人数
List<String> collect = Stream.concat(users.stream(), users1.stream()).distinct().map(User::getName).collect(Collectors.toList());
System.out.println("两个队队员的总人数"+collect);
//两个队伍薪资最高的前四名
List<String> collect1 = Stream.concat(users.stream(), users1.stream()).distinct().collect(Collectors.toList()).stream().sorted(Comparator.comparing(User::getSalary).reversed())
.limit(4).map(User::getName).collect(Collectors.toList());
System.out.println("两个队伍薪资最高的前四名"+collect1);
//跳过两个队伍薪资最高的前四名前两人
List<String> collect2 = collect1.stream().skip(2).collect(Collectors.toList());
System.out.println("跳过两个队伍薪资最高的前四名前两人"+collect2);
}
输出:
两个队队员的总人数[xiaoHu, LetMe, Mlxg, xiaoMing, Miss, Uzi, Gala, Wei, YuShuang, Cryin]
两个队伍薪资最高的前四名[Uzi, Cryin, Miss, YuShuang]
跳过两个队伍薪资最高的前四名前两人[Miss, YuShuang]