Stream流是Java8新添加的一种声明的方式处理数据方式,Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。支持筛选、排序、聚合等。对于任何一项技术,每个人都有自己独到的见解,有些人习惯在理论上分析,有些人习惯在实践中提升,这都不影响我们灵活运用这项技术。我这边通过一个方法整理出日常开发中经常用到Stream的技术点,说实话,对于常规的数据处理,真的太方便了~
首先,做个拓展,从一个txt中读数据,作为一名优秀的程序员,不能一直拘泥于在数据库中读数据啊。。。
在项目的根目录下,放入我们的数据源
打开txt,数据是这样子的:
构造一个实体,用来解析数据:
@Data
@ToString
@Builder
public class User {
private Long userId;
private String name;
private String sex;
private Long age;
private Long score;
private String city;
}
然后,我们就可以通过下面这个方法,获取数据源,大胆测试啦!
public static List<User> getUserList(){
List<User> users = Lists.newArrayList();
try {
FileInputStream out = new FileInputStream(System.getProperty("user.dir") + File.separator + "test.txt");
InputStreamReader reader = new InputStreamReader(out, StandardCharsets.UTF_8);
BufferedReader in = new BufferedReader(reader);
String line = null;
while ((line = in.readLine()) != null) {
String newline = line.replaceAll("[\t]", " ");
String[] arr = newline.split(" ");
Long userId = Long.valueOf(arr[0]);
String name = arr[1];
String sex = arr[2];
Long age = Long.valueOf(arr[3]);
Long score = Long.valueOf(arr[4]);
String city = arr[5];
User user = User.builder().userId(userId).name(name).sex(sex).age(age).score(score).city(city).build();
users.add(user);
}
} catch (IOException e) {
e.printStackTrace();
}
return users;
}
接下来,我们的重点来了,以下是我们Stream的应用实例,看看如何?
public static void main(String[] args) {
List<User> users = getUserList();
System.out.println(">>>打印原始集合:"+users.toString());
System.out.println("******************************************************************");
//1、map的用法,通过map可以构造出新的对象或属性返回。例如:通过Stream.map获取年龄的集合
List<Long> ages = users.stream().map(item -> {
return item.getAge();
}).collect(Collectors.toList());
System.out.println(">>>通过map获取到年龄的集合:"+ages.toString());
System.out.println("******************************************************************");
//2、filter的用法,通过设置的条件过滤出元素
//2-1 获取性别为女的集合
List<User> females = users.stream().filter(item -> item.getSex().equals("女")).collect(Collectors.toList());
System.out.println(">>>通过filter获取到性别为女的集合:"+females.toString());
//2-2 获取性别为女的数量
Long femaleCount = users.stream().filter(item -> item.getSex().equals("女")).count();
System.out.println(">>>通过filter获取到性别为女的数量:"+femaleCount);
//2-3 获取姓名为邢道荣的对象
User user1 = users.stream().filter(item -> item.getName().equals("邢道荣")).findFirst().get();
System.out.println(">>>通过filter获取到姓名为邢道荣的对象:"+user1.toString());
//2-4 filter+map聚合获取姓名为邢道荣的分数
Long score1 = users.stream().filter(item -> item.getName().equals("邢道荣")).map(item -> {
return item.getScore();
}).findFirst().get();
System.out.println(">>>通过filter+map聚合获取到姓名为邢道荣的分数:"+score1);
System.out.println("******************************************************************");
//3、sorted的用法,可以快读对list排序
//3-1 按照年龄升序对集合排序
List<User> ageAscs = users.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
System.out.println(">>>通过sorted按照年龄升序对集合排序:"+ageAscs.toString());
//3-2 按照分数降序对集合排序
List<User> scoDescs = users.stream().sorted(Comparator.comparing(User::getScore,Comparator.reverseOrder()))
.collect(Collectors.toList());
System.out.println(">>>通过sorted按照分数降序对集合排序:"+scoDescs.toString());
//3-3 混合排序,按照分数升序、年龄降序对集合排序
List<User> scoAscs = users.stream().sorted(Comparator.comparing(User::getScore)
.thenComparing(User::getAge,Comparator.reverseOrder())).collect(Collectors.toList());
System.out.println(">>>通过sorted按照分数升序、年龄降序对集合排序:"+scoAscs.toString());
System.out.println("******************************************************************");
//4、groupingBy的用法,可以根据某字段(或多个字段)把List分类成Map嵌套List的结构,把List按照字段归类
//4-1 按照性别对集合归类
Map<String, List<User>> map1 = users.stream().collect(Collectors.groupingBy(User::getSex));
System.out.println(">>>通过groupingBy按照性别对集合归类:"+map1.toString());
//4-2 先按照性别、再按照城市对集合归类
Map<String, Map<String, List<User>>> map2 = users.stream().collect(Collectors.groupingBy(
User::getSex, Collectors.groupingBy(User::getCity)));
System.out.println(">>>通过groupingBy先按照性别、再按照城市对集合归类:"+map2.toString());
System.out.println("******************************************************************");
//5、distinct的用法,去重
List<String> sexs = users.stream().map(item -> {
return item.getSex();
}).distinct().collect(Collectors.toList());
System.out.println(">>>通过distinct对性别集合去重:"+sexs.toString());
System.out.println("******************************************************************");
//6、mapTo*的用法,用于常规数值计算:平均值、最大值、最小值、求和
//6-1 平均值
double avAge = users.stream().mapToLong(item -> item.getAge()).average().getAsDouble();
System.out.println(">>>通过average求平均年龄:"+avAge);
//6-2 最大值
Long maxAge = users.stream().mapToLong(item -> item.getAge()).max().getAsLong();
System.out.println(">>>通过max求最大年龄:"+maxAge);
//6-3 最小值
Long minAge = users.stream().mapToLong(item -> item.getAge()).min().getAsLong();
System.out.println(">>>通过max求最小年龄:"+minAge);
//6-4 求和
Long sumScore = users.stream().mapToLong(item -> item.getScore()).sum();
System.out.println(">>>通过sum求所有人分数总和:"+sumScore);
//6-5 聚合算法
double avgScore = users.stream().filter(item->item.getCity().equals("上海"))
.mapToLong(item -> item.getScore()).average().getAsDouble();
System.out.println(">>>通过filter+average求来自上海的平均分:"+avgScore);
System.out.println("******************************************************************");
}
最终运行的结果:
>>>打印原始集合:[User(userId=1, name=张三, sex=男, age=20, score=99, city=上海), User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京), User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海)]
******************************************************************
>>>通过map获取到年龄的集合:[20, 19, 23, 17, 45, 37, 35]
******************************************************************
>>>通过filter获取到性别为女的集合:[User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海)]
>>>通过filter获取到性别为女的数量:4
>>>通过filter获取到姓名为邢道荣的对象:User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京)
>>>通过filter+map聚合获取到姓名为邢道荣的分数:88
******************************************************************
>>>通过sorted按照年龄升序对集合排序:[User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=1, name=张三, sex=男, age=20, score=99, city=上海), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海), User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海), User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京)]
>>>通过sorted按照分数降序对集合排序:[User(userId=1, name=张三, sex=男, age=20, score=99, city=上海), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海), User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海)]
>>>通过sorted按照分数升序、年龄降序对集合排序:[User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海), User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=1, name=张三, sex=男, age=20, score=99, city=上海)]
******************************************************************
>>>通过groupingBy按照性别对集合归类:{
女=[User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海)], 男=[User(userId=1, name=张三, sex=男, age=20, score=99, city=上海), User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京), User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海)]}
>>>通过groupingBy先按照性别、再按照城市对集合归类:{
女={
上海=[User(userId=2, name=李四, sex=女, age=19, score=93, city=上海), User(userId=7, name=凤姐, sex=女, age=35, score=82, city=上海)], 北京=[User(userId=3, name=王五, sex=女, age=23, score=88, city=北京), User(userId=4, name=赵六, sex=女, age=17, score=95, city=北京)]}, 男={
上海=[User(userId=1, name=张三, sex=男, age=20, score=99, city=上海), User(userId=6, name=潘凤, sex=男, age=37, score=79, city=上海)], 北京=[User(userId=5, name=邢道荣, sex=男, age=45, score=88, city=北京)]}}
******************************************************************
>>>通过distinct对性别集合去重:[男, 女]
******************************************************************
>>>通过average求平均年龄:28.0
>>>通过max求最大年龄:45
>>>通过max求最小年龄:17
>>>通过sum求所有人分数总和:624
>>>通过filter+average求来自上海的平均分:88.25
******************************************************************
完结