第5章 使用流
本章内容
1.筛选、切片和匹配
2.查找、匹配和归约
3.使用数值范围等数值流
4.从多个源创建流
5.无限流
5.1 筛选和切片
用谓词筛选,筛选出各不相同的元素,忽略流中的头几个元素,或将流截短至指定长度。
5.1.1 用谓词筛选
就是filter方法,filter()里面的参数是一个布尔值函数,然后会返回为true的流。
5.1.2 筛选各异的元素
使用distinct()方法,就是会去除重复的数据
@Test
public void test(){
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);
}
结果: 2 4
5.1.3 截短流
@Test
public void test(){
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.limit(1)
.forEach(System.out::println);
}
结果 2
5.1.4 跳过元素
skip(n),丢掉前n个元素的流,如果流中元素不足n个会返回一个空流。
@Test
public void test(){
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.skip(1)
.forEach(System.out::println);
}
2 1 3 3 2 4
5.2 映射
流支持map方法,它会接受一个函数作为参数,这个函数会应用到每个元素之上,然后会将其映射成一个新元素。
List<String> dishNames = menu.stream()
.map(Dish::getName)
.collect(Collectors.toList());
上面这个就是把Dish::getName方法传给了map,作用于所有的元素,但在map方法处理后输出的还是流是Stream
5.2.1 流的扁平化
例:如果将一个单词列表[“Hello”,“World”]想转化为[“H”,“e”,“l”, “o”,“W”,“r”,“d”]
public static void main(String[] args) {
List<String> words = new ArrayList<>();
words.add("Hello");
words.add("World");
List<String[]> list = words.stream()
.map(word -> word.split(""))
.distinct()
.collect(Collectors.toList());
}
words.stream()
.map(item -> item.split("")) Stream<String[]>
.distinct() Stream<String[]>
.collect(toList()); List<String[]>
返回的是List<String[]>并非List<String>
但这么处理map返回的是Stream<String[ ]>类型(先是把每个单词转换成一个字母数组,然后把每个数组变成了一 个独立的流),而正确的处理应该是用Stream来表示一个流。
这里就可以使用flatMap来解决这个问题
List<String> uniqueCharacters = words.stream()
.map(w -> w.split(""))
.flatMap(Arrays::stream)
.distinct()
.collect(Collectors.toList());
flatMap(Arrays::stream) 会将单个流合并起来。
5.3 查找和匹配
另一个常见的数据处理套路是看看数据集中的某些元素是否匹配一个给定的属性。Stream API通过allMatch、anyMatch、noneMatch、findFirst和findAny方法提供了这样的工具。
allMatch: 流中所有元素是否能够匹配给定的谓词
anyMatch:流中是否有一个元素能够匹配给定的谓词
noneMatch:没有任何元素与给定的谓词匹配
findAny:返回当前流中的任意元素,可以与其他流操作结合使用。
Optional<Dish> dish = menu.stream()
.filter(Dish::isVegetarian)
.findAny();
补充一个无关的:
Optional.ofNullable(mp.selectList(queryWrapper)).orElse(new ArrayList<>(0));
5.4 规约
5.4.1 元素求和
int sum = numbers.stream().reduce(0 , (a,b)->a+b);
int sum = numbers.stream().reduce(0 , Integer::sum);
5.4.2 最大值和最小值
Optional<Integer> max = numbers.stream().reduce(Integer::max); ```
```java
Optional<Integer> min = numbers.stream().reduce(Integer::min);
comparing补充
附录
// 获取结果中的排期id与用户id,其中key为排期id,value为该排期下所有用户id的集合
Map<Integer, List<String>> userAndScheduleMaps = scheduleStudentPage.getRecords().stream()
.collect(Collectors.groupingBy(CourseScheduleStudentEntity::getCourseScheduleId,
Collectors.mapping(CourseScheduleStudentEntity::getUserId, Collectors.toList())));
部分无关代码记录
Map map = new HashMap(); //定义Map集合对象
map.put("apple", "新鲜的苹果"); //向集合中添加对象
map.put("computer", "配置优良的计算机");
map.put("book", "堆积成山的图书");
Collection values = map.values(); //获取Map集合的value集合
for (Object object : values) {
System.out.println("键值:" + object.toString()); //输出键值对象
}
键值:新鲜的苹果
键值:配置优良的计算机
键值:堆积成山的图书
过滤不为空
List<Object> departmentIds = staffInfoList.parallelStream()
.map(FeishuStaffsEntity::getOpenDepartments)
.distinct()
.filter(Objects::nonNull)
.collect(Collectors.toList());
LambdaQueryWrapper<EArticleAnchorEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(EArticleAnchorEntity::getArticleId, articleId)
.eq(EArticleAnchorEntity::getAnchor, articleAnchor);
EArticleAnchorEntity eArticleAnchorInfo = eArticleAnchorDao.getOne(queryWrapper,false);
Validator.notNull(eArticleAnchorInfo,"参数错误:未找到锚点记录");
private Map<String, CourseReportBo> getReportAndState(Page<CourseScheduleStudentEntity> scheduleStudentPage) {
// 获取结果中的排期id与用户id,其中key为排期id,value为该排期下所有用户id的集合
Map<Integer, List<String>> userAndScheduleMaps = scheduleStudentPage
.getRecords()
.stream()
.collect(Collectors.groupingBy(CourseScheduleStudentEntity::getCourseScheduleId,
Collectors.mapping(CourseScheduleStudentEntity::getUserId, Collectors.toList())));
// 获取用户report报告
LambdaQueryWrapper<StatisticCourseSheduleStudentEntity> conds = new LambdaQueryWrapper<>();
userAndScheduleMaps.entrySet().stream().forEach(userAndScheduleMap -> {
conds.or(idEntity -> {
idEntity.eq(StatisticCourseSheduleStudentEntity::getCourseScheduleId, userAndScheduleMap.getKey());
idEntity.in(StatisticCourseSheduleStudentEntity::getUserId, userAndScheduleMap.getValue());
});
});
List<StatisticCourseSheduleStudentEntity> entityResult = statisticCourseSheduleStudentDao.listByConds(conds);
return entityResult.stream().filter(
entity -> StringUtils.isNotBlank(entity.getReport()))
.collect(Collectors.toMap(
entity -> entity.getCourseScheduleId() + ":" + entity.getUserId(),
entity -> JSONObject.parseObject(entity.getReport(), CourseReportBo.class)
));
}
.sorted(Comparator.comparing(StudentExamRecordVo::getChapterName)
.thenComparing(StudentExamRecordVo::getSectionName)
.thenComparing(StudentExamRecordVo::getStartTime))
.collect(Collectors.toList());