Java 8新特性之流处理

1.定义

简单定义就是,从支持数据处理操作的源生成的元素序列

  • 数据处理——类似于数据库的操作,不用关心是怎么做i的,只需知道做什么的。
  • 元素序列——像集合一样,可以访问特定元素类型的一组有序值。
  • 源——流会使用一个提供数据的源,会保留原有的顺序。
    注意:流只能消费一次,

2.流操作

流的操作基本上可以分为两大类,中间操作和终端操作。

2.1 中间操作

中间操作会返回另一个流

2.2 终端操作

终端操作会从流的流水线生成结果。

3.中间操作

接下来用到list内容都如下所示(特殊说明除外)

class User{
private Long id;       //主键id
private String name;   //姓名
private Integer age;   //年龄
private String school; //学校
public User(Long id, String name, Integer age, String school) {
   this.id = id;
   this.name = name;
   this.age = age;
   this.school = school;
}
//此处省略get、set方法。。。

/*================================================*/
List<User> list = new ArrayList<User>(){
    {
        add(new User(1l,"张三",10, "清华大学"));
        add(new User(2l,"李四",12, "清华大学"));
        add(new User(3l,"王五",15, "清华大学"));
        add(new User(4l,"赵六",12, "清华大学"));
        add(new User(5l,"田七",25, "北京大学"));
        add(new User(6l,"小明",16, "北京大学"));
        add(new User(7l,"小红",14, "北京大学"));
        add(new User(8l,"小华",14, "浙江大学"));
        add(new User(9l,"小丽",17, "浙江大学"));
        add(new User(10l,"小何",10, "浙江大学"));
    }
};

3.1 筛选和切片

3.1.1 用谓词筛选(filter方法)

该方法会接收一个谓词(一个返回boolean的函数)作为参数,并返回一个包括所有符合谓词的元素的流。

//筛选出北京大学的学生
list.stream()
	.filter(x -> "北京大学".equals(x.getSchool()))
	.collect(Collectors.toList());
3.1.2 筛选各异的元素(distinct方法)

返回一个元素各异的流,即没有重复的元素。

//查询所有的学校(不重复)
list.stream()
	.map(User::getSchool)
	.distinct()
	.collect(Collectors.toList());
3.1.3 截短流(limit方法)

该方法会返回一个不超过给定长度的流

//获取年龄是偶数的前2名学生
list.stream()
	.map(o -> o.getAge() % 2 == 0)
	.limit(2)
	.collect(Collectors.toList());
3.1.4 跳过元素(skip方法)

该方法返回了一个扔掉了前n个元素的流,如果流中元素不足n个,则返回一个空流。

//跳过前2个学生的所有学生
list.stream()
	.skip(2)
	.collect(Collectors.toList());

3.2 映射

3.2.1 map方法

map方法接受一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素。

//显示每个单词中有几个字母
List<String> words = Arrays.asList("Java 8", "Lambdas", "In", "Action");
List<Integer> wordLengths = words.stream()
								.map(String::Length)
								.collect(toList());
3.2.2 flapMap

一个单词数组,想要返回一张列表,列出里面各不相同的字符,例如,给定单词列表[“hello”,“world”],返回的结果是[“h”,“e”,“l”,“o”,“w”,“r”,“l”,“d”]。
第一版本,先将单词映射成一张字符表,然后再用distinct过滤,得到结果。

words.stream()
 .map(word -> word.split(""))
 .distinct()
 .collect(toList()); 

不正确地使用map找出单词列表中各不相同的字符
使用流扁平化

List<String> uniqueCharacters =
 words.stream()
 .map(w -> w.split(""))
 .flatMap(Arrays::stream)
 .distinct()
 .collect(Collectors.toList());

使用flatMap方法的效果是,各个数组并不是分别映射成一个流,而是映射成流的内容。所
以使用flapMap(Arrays::stream)时生成的单个流都被合并起来,即扁平化为一个流。
使用flatMap找出单词列表中各不相同的字符

3.3 排序

//按照学生的年龄升序排序
list.stream()
	.sorted((s1,s2) -> s1.getAge() - s2.getAge())
	.collect(Collectors.toList());

4.终端操作

前面提及到的collect()是其中一个终端操作,除此之外,还有allMatch、anyMatch
、foreach等

4.1 allMatch

判断是否所有的元素都满足指定的参数行为,都满足返回true。

//判断是否全部学生的年龄大于9
Boolean b = list.stream()
	.allMatch(user -> user.getAge() > 9)
	

4.2 anyMatch

判断是否有一个或多个元素满足条件,有则返回true

//是否有学生是北京大学的
Boolean b = list.stream()
	.anyMatch(user -> "北京大学".equals(user.getSchool()));

4.3 findFirst、finfAny

findFirst:找到第一个符合条件的元素。
findAny:找到任意一个符合条件的元素,找到则返回元素。

//找到第一个年龄大于18的学生
Optional<User> = optional = list.stream()
	.filter(user -> user.getAge() > 18)
	.findFirst();
User user  = optional.get();

//找到任意一个年龄大于18的学生
Optional<User> = optional = list.stream()
	.filter(user -> user.getAge() > 18)
	.findAny();
User user  = optional.get();

4.4 reduce

reduce(归约),将经过参数化操作的集合进行进一步的运算,返回的不是一个集合,可能是一个数值,比如总和。

Integer sum = list.stream()
	.filter(user -> user.getAge() > 18)
	.reduce(0, (a,b) -> a+b);
//还有其他几种写法
//1
Integer sum1 = list.stream()
	.filter(user -> user.getAge() > 18)
	.reduce(0, Integer::sum);
//2
Optional<Integer> optional = list.stream()
	.filter(user -> user.getAge() > 18)
	.reduce(Integer::sum);
if(optional.isPresent()) {
	Integer sum2 = optional.get();
}
//3
int sum3 = list.stream()
	.filter(user -> user.getAge() > 18)
	.mapToInt(User::getAge).sum();

4.5 收集

counting:计算个数(list集合的话用size()方法更方便)
maxBy:计算最大值
minBy:计算最小值
joining:拼接字符串

//统计总共有多少学生
list.stream().count();
list.stream().collect(Collectors.counting());

//获取最大的年龄
list.stream().collect(Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge())).get().getAge();
list.stream().collect(Comparetor.comparing(User::getAge)).get().getAge();
list.stream().max(Comparetor.comparing(User::getAge)).get().getAge();

//将学生的姓名用","拼接 张三,李四.....
list.stream().map(User::getName).collect(Collectors.joining(","));

groupBy 分组

//按学校分组
Map<String, List<User>> collect = list.stream().collect(Collectors.groupingBy(User::getSchool));
collect.forEach((s, users) -> System.out.println(s + ": " + users.toString));

//先按学校分组,再按年龄分组
Map<String, Map<Integer, List<User>>> collect1 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge)));
collect1.forEach((s, map) -> System.out.println(s + ": " + map));

//统计每个学校不同年龄的人数
Map<String, Map<Integer, Long>> collect2 = list.stream().collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.counting())));
collect2.forEach((s, map) -> System.out.println(s + ": " + map));

运行结果
运行结果

partitionBy 分区
根据条件将数据分成两部分,一边是符合条件的,一边是不符合条件的。

//根据条件“是否是清华大学的学生”将学生信息分为两部分
Map<Boolean, List<User>> collect = list.stream().collect(Collectors.partitioningBy(user -> "清华大学".equals(user.getSchool())));

运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值