本文将以UmsMenu对象为例来介绍Stream API的常用操作。UmsMenu是一个菜单对象,具有树形结构,对象定义如下
Stream对象的创建
Stream对象分为两种,一种串行的流对象,一种并行的流对象。
1 // menuList指所有菜单列表 2 // 为集合创建串行流对象 3 Stream<UmsMenu> stream = menuList.stream(); 4 // 为集合创建并行流对象 5 Stream<UmsMenu> parallelStream = menuList.parallelStream();
filter
对Stream中的元素进行过滤操作,当设置条件返回true时返回相应元素。
1 @Test 2 public void filterTest(){ 3 //filter操作:获取所有一级菜单 4 List<UmsMenu> oneLevelList = menuList.stream() 5 .filter(menu -> menu.getParentId() == 0L) 6 .collect(Collectors.toList()); 7 LOGGER.info("filter操作:{}",oneLevelList); 8 }
map
对Stream中的元素进行转换处理后获取,比如可以将UmsMenu对象转换成Long对象。我们经常会有这样的需求:需要把某些对象的id提取出来,然后根据这些id去查询其他对象,这时可以使用此方法。
1 @Test 2 public void mapTest(){ 3 //map操作:获取所有菜单的id 4 List<Long> idList = menuList.stream() 5 .map(menu -> menu.getId()) 6 .collect(Collectors.toList()); 7 LOGGER.info("map操作:{}",idList); 8 }
limit
从Stream中获取指定数量的元素。
1 @Test 2 public void limitTest(){ 3 //limit操作:获取前5个菜单 4 List<UmsMenu> firstFiveList = menuList.stream() 5 .limit(5) 6 .collect(Collectors.toList()); 7 LOGGER.info("limit操作:{}",firstFiveList); 8 }
count
仅获取Stream中元素的个数。
1 @Test 2 public void countTest(){ 3 //count操作:获取所有一级菜单的个数 4 long count = menuList.stream() 5 .filter(menu -> menu.getParentId() == 0L) 6 .count(); 7 LOGGER.info("count操作:{}",count); 8 }
sorted
对Stream中元素按指定规则进行排序。
1 @Test 2 public void sortedTest(){ 3 //sorted操作:将所有菜单按照sort字段进行排序 4 List<UmsMenu> sortedList = menuList.stream() 5 .sorted((menu1,menu2)->{return menu2.getSort().compareTo(menu1.getSort());}) 6 .collect(Collectors.toList()); 7 LOGGER.info("sorted操作:{}",sortedList); 8 }
skip
跳过指定个数的Stream中元素,获取后面的元素。
1 @Test 2 public void skipTest(){ 3 //skip操作:跳过前5个元素,返回后面的 4 List<UmsMenu> skipList = menuList.stream() 5 .skip(5) 6 .collect(Collectors.toList()); 7 LOGGER.info("skip操作:{}",skipList); 8 }
用collect方法将List转成map
有时候我们需要反复对List中的对象根据id进行查询,我们可以先把该List转换为以id为key的map结构,然后再通过map.get(id)来获取对象,这样比较方便。
1 @Test 2 public void collect2mapTest(){ 3 //collect转map操作:将菜单列表以id为key,以菜单对象为值转换成map 4 Map<Long, UmsMenu> menuMap = menuList.stream() 5 .collect(Collectors.toMap(menu -> menu.getId(), menu -> menu)); 6 LOGGER.info("collect转map操作:{}",menuMap); 7 }
应用
我们经常会有返回树形结构数据的需求。比如这里的菜单,具有一级菜单、二级菜单、三级菜单这样的结构。如果我们要返回一个集合,包含菜单以及菜单下面嵌套的子菜单,使用Stream API可以很方便的解决这个问题。
注意:这里我们的菜单上下级之间以parentId来关联,parentId是指上一级菜单的id,顶级菜单的parentId为0。
定义获取树形结构的方法
我们先过滤出parentId为0的顶级菜单,然后给每个顶级菜单设置其子级菜单,covertMenuNode方法的主要用途就是从所有菜单中找出相应子级菜单。
1 @Override 2 public List<UmsMenuNode> treeList() { 3 List<UmsMenu> menuList = menuMapper.selectByExample(new UmsMenuExample()); 4 List<UmsMenuNode> result = menuList.stream() 5 .filter(menu -> menu.getParentId().equals(0L)) 6 .map(menu -> covertMenuNode(menu, menuList)).collect(Collectors.toList()); 7 return result; 8 }
为每个菜单设置子级菜单
这里我们使用filter操作来过滤出每个菜单的子级菜单,由于子级菜单下面可能还会有子级菜单,这里我们使用递归来解决。但是递归操作什么时候停止,这里把递归调用方法放到了map操作中去,当没有子级菜单时filter下的map操作便不会再执行,从而停止递归。
/** * 将UmsMenu转化为UmsMenuNode并设置children属性 */ private UmsMenuNode covertMenuNode(UmsMenu menu, List<UmsMenu> menuList) { UmsMenuNode node = new UmsMenuNode(); BeanUtils.copyProperties(menu, node); List<UmsMenuNode> children = menuList.stream() .filter(subMenu -> subMenu.getParentId().equals(menu.getId())) .map(subMenu -> covertMenuNode(subMenu, menuList)).collect(Collectors.toList()); node.setChildren(children); return node; }
标签:map,菜单,Stream,menu,List,jdk8,使用,StreamAPI,menuList From: https://www.cnblogs.com/hnzj/p/18113427