Java 8 新特性 Stream流-Lambda表达式的简单使用
stream流全是在内存中进行操作,将数据进行全查,使用stream()流处理数据,这个是专门来处理集合的,java8 中的新特新就新在hashmap里面的数据存储上进行了改进,对数据建立索引,而且是不同的hash计算所得的数据,里面也重写了hashcode和eques方法,当两个数据的地址相同时就会判断两个数据的值是否相等,相等的话就会重新制定一个位置,当长度大于8 ,存储的大于64时就扩展为一个二叉树。这样大大的增加了它的查询效率,而在stream流中应用了lamda表达式。在比较一个id时,会对这个数据进行hash的计算,然后去找这个值,远远的减小了搜寻的范围提高了查询的效率,
话不多说直接上代码
业务要求,现在要查询展示一个树状结构的数据,比如一个地产开发项目,一个表里有总部(1级),城市(2),区域(3),项目(4),地块(5)这些,它们就像是省市县一样有层级关系的,现在想实现的功能是根据某一个id去查询这个id锁对应下的所有数据,并且查询出来的是以树结构展示的数据,
/**
* 根据id查询树状组织架构
*
* @param id
* @return
*/
@ApiOperation(value = "根据id查询树状组织架构")
@GetMapping(value = "tree")
public RespResult selectTree(String id) {
RespResult respResult = new RespResult<>();
try {
// 先查询出所有的数据
List<OrganizationsResultExt> all = organizationsService.findAll();
//使用for循环来遍历获取每一条数据的id
for (OrganizationsResultExt organizationsResultExt : all) {
if (id.equals(organizationsResultExt.getId())) {
// Item中存储的是它的下一层数据
organizationsResultExt.setItems(getChildren(all, id));
respResult.setData(organizationsResultExt);
}
}
} catch (Exception ex) {
LogUtil.logApplicationInfo("根据id查询树状组织架构请求错误", ex);
respResult.setMsg(ResultEnum.DELETE_ERROE.getMsg());
}
return respResult;
}
这是递归查询
/**
* 递归进行查询子部门方法
*
* @param id
* @return
*/
public List<OrganizationsResultExt> getChildren(List<OrganizationsResultExt> all, String id) {
List<OrganizationsResultExt> list = new ArrayList<>();
// 从所有数据中遍历
for (OrganizationsResultExt organizationsExtVo : all) {
// 比对遍历出来的数据的父id是否与当前查询数据的id值相同,相同就添加到集合中
if (id.equals(organizationsExtVo.getParentId())) { organizationsExtVo.setItems(getChildren(all, organizationsExtVo.getId()));
list.add(organizationsExtVo);
}
}
return list;
}
这种实现方式是最容易想到的,但是这样把操作数据库的语句放到了循环中,频繁操作数据库是费时且不安全的,一个接口可能占用了过大的资源,所以这也是效率方面禁止的写法
第二种:
/**
* 根据id查询树状组织架构
*
* @param id
* @return
*/
@ApiOperation(value = "根据id查询树状组织架构")
@GetMapping(value = "tree")
public RespResult selectTree(String id) {
RespResult respResult = new RespResult<>();
try {
OrganizationsResultExt organizationsExts = organizationsService.findById(id);
organizationsExts.setItems(getChildren(id));
respResult.setData(organizationsExts);
} catch (Exception ex) {
LogUtil.logApplicationInfo("根据id查询树状组织架构请求错误", ex);
respResult.setMsg(ResultEnum.DELETE_ERROE.getMsg());
}
return respResult;
}
/**
* 递归进行查询子部门方法
*
* @param id
* @return
*/
public List<OrganizationsResultExt> getChildren( String id) {
List<OrganizationsResultExt> list = new ArrayList<>();
// 使用当前数据的id当做父id来查询,这样获取到这个id下所有的子数据,在遍历每条数据,并且使用当前遍历
// 出来的数据id作为id再次调用
/**
*使用当前数据的id当做父id来查询,这样获取到这个id下所有的子数据,在遍历每条数据,并且使用当前遍历出来的
数据id再掉当前方法作为父id去查询。
*/
List<OrganizationsResultExt> organizationsExtList = organizationsService.findByParentId(id);
for (OrganizationsResultExt organizationsExtVo : organizationsExtList) {
organizationsExtVo.setItems(getChildren(organizationsExtVo.getId()));
list.add(organizationsExtVo);
}
return list;
Stream流形式,当是项目或者地块时就为他设置SpaceId
* 获取组织结构树
*
* @param orgzId 组织机构ID
* @return
*/
@Override
public RespResult selectTree(String orgzId) {
RespResult respResult = new RespResult<>();
String orgTreeListStr = redisUtils.get(OrganizationConstant.ORGANIZATION_TREE_LIST + orgzId);
if (StringUtils.isNotEmpty(orgTreeListStr)) {
respResult = JSON.parseObject(orgTreeListStr, RespResult.class);
} else {
// 对组织进行全查
List<OrganizationResultExt> organizationsResultExtList = this.findAll();
// 项目数据全查
List<ProjectExt> projectsExtList = projectService.findAll();
// 地块数据全查
List<BlockExt> blocksExtList = blockService.findAll();
// 根据传进来的id进行数据查询
OrganizationResultExt organizationsResultExt = this.findOrganizationById(orgzId);
// 若当前数据的level值为3(地块)或者4(项目)时,为字段设置SpaceId值
if (organizationsResultExt.getLevel() == OrganizationConstant.PROJECT ||
organizationsResultExt.getLevel() == OrganizationConstant.BLOCK) {
addProjectAndBlock(organizationsResultExt, projectsExtList, blocksExtList, orgzId);
}
organizationsResultExt.setItems(getChildren(organizationsResultExtList, projectsExtList, blocksExtList, orgzId));
respResult.setCode(ResultEnum.SUCCESS.getCode());
respResult.setMsg(ResultEnum.SUCCESS.getMsg());
respResult.setData(organizationsResultExt);
String orgTeeStr = JSON.toJSONString(respResult);
redisUtils.set(OrganizationConstant.ORGANIZATION_TREE_LIST + orgzId, orgTeeStr, OrganizationConstant.ORGANIZATION_CACHE_SECONDS);
}
return respResult;
}
递归查询
/**
* 递归进行查询子部门方法
*
* @param organizationsResultExtList 组织的数据
* @param projectsExtList 项目的数据集合
* @param blocksExtList 地块的数据集合
* @param id 查询的id
*/
private List<OrganizationResultExt> getChildren(List<OrganizationResultExt> organizationsResultExtList,
List<ProjectExt> projectsExtList,
List<BlockExt> blocksExtList,
String id) {
List<OrganizationResultExt> list = new ArrayList<>();
organizationsResultExtList.stream().filter(o -> id.equals(o.getParentId()))
.forEach((organizationsExt) -> {
if (organizationsExt.getLevel() == OrganizationConstant.PROJECT || organizationsExt.getLevel() == OrganizationConstant.BLOCK) {
addProjectAndBlock(organizationsExt, projectsExtList, blocksExtList, organizationsExt.getId());
}
organizationsExt.setItems(getChildren(organizationsResultExtList, projectsExtList, blocksExtList, organizationsExt.getId()));
list.add(organizationsExt);
});
return list;
}
/**
* 向组织的数据中设置SpaceId值
*
* @param organizationsResultExt 组织的数据
* @param projectsExtList 项目的数据集合
* @param blocksExtList 地块的数据集合
* @param id 查询的id
*/
private void addProjectAndBlock(OrganizationResultExt organizationsResultExt,
List<ProjectExt> projectsExtList,
List<BlockExt> blocksExtList,
String id) {
Optional<ProjectExt> optionalProjectsExt = projectsExtList.stream().filter(o -> id.equals(o.getOgzId())).findFirst();
// 判断optionalProjectsExt里面是否有值
if (optionalProjectsExt.isPresent()) {
organizationsResultExt.setSpaceId(optionalProjectsExt.get().getOgzId());
}
// 判断这个id是否与地块集合中的某一条数据的OgzId相同
Optional<BlockExt> optionalBlocksExt = blocksExtList.stream().filter(o -> id.equals(o.getOgzId())).findFirst();
// 判断optionalProjectsExt里面是否有值
if (optionalBlocksExt.isPresent()) {
organizationsResultExt.setSpaceId(optionalBlocksExt.get().getId());
}
}
Stream流的使用三步
创建流:projectsExtList.stream(),
中间操作:.filter(o -> id.equals(o.getOgzId())),
结束操作:.findFirst()
返回的是一个Optional,这个是被处理过的,当没查询到数据时,自己添加一个对象防止空指针,
所以这个如果没查到数据不能用null来判断,需要使用.isPresent()方法来判断,这个对象里是否有值。然后再做后边操作。