Arrays.asList(new Person("1", "hah"), new Person("1", "hh"))
.stream().peek(p -> p.setId("222")).forEach(System.out::println);
@AllArgsConstructor
@Data
public static class Person {
private String id;
private String name;
}
TestMain.Person(id=222, name=hah)
TestMain.Person(id=222, name=hh)
List<Integer> list = Arrays.asList(4, 7, 9, 11, 12);
list.stream().peek(x -> System.out.println("基本打印:" + x))
//每个元素+2,在用 分别打印。变成了:6 9 11 13 14
.map(x -> x + 2).peek(x -> System.out.println("map:" + x))
//9 11 13 ,是奇数,才打印
.filter(x -> x % 2 != 0).peek(x -> System.out.println("filter:" + x))
//只取 前 2个,那就是 9 和 11 了。
.limit(2).peek(x -> System.out.println("limit:" + x))
.collect(Collectors.toList()); //只有终止的时候,才执行peek
基本打印:4
map:6
基本打印:7
map:9
filter:9
limit:9
基本打印:9
map:11
filter:11
limit:11
//只取 前2个,打印 9 和 11
直接limit2打印:
基本打印:4
limit:4
基本打印:7
limit:7
list.stream().peek(x -> System.out.println("基本打印:" + x))
.filter(x -> x % 2 != 0).peek(x -> System.out.println("filter:" + x))
.collect(Collectors.toList());
基本打印:4
基本打印:7
filter:7
基本打印:9
filter:9
基本打印:11
filter:11
基本打印:12
//基本打印了 5个数。 过滤打印了:7 9 11三个数。
//在limit2,是在 7 9 11种 取2个的。
基本打印:4
基本打印:7
filter:7
limit:7
基本打印:9
filter:9
limit:9
java 8 Stream中操作类型和peek的使用
java 8 stream作为流式操作有两种操作类型,中间操作和终止操作。这两种有什么区别呢?
我们看一个peek的例子:
Stream<String> stream = Stream.of("one", "two", "three","four");
stream.peek(System.out::println);
上面的例子中,我们的本意是打印出Stream的值,但实际上没有任何输出。
为什么呢?
一个java 8的stream是由三部分组成的。
中间操作是对数据的加工,
终止操作是stream的启动操作,
所以,问题解决了,peek是一个中间操作,所以上面的例子没有任何输出。
我们看下peek的文档说明:peek主要被用在debug用途。
我们看下debug用途的使用:
Stream.of("one", "two", "three","four")
.filter(e -> e.length() > 3).peek(e -> System.out.println("Filtered value: " + e))
.map(String::toUpperCase).peek(e -> System.out.println("Mapped value: " + e))
.collect(Collectors.toList());
上面的例子输出:
Filtered value: three
Mapped value: THREE
Filtered value: four
Mapped value: FOUR
上面的例子我们输出了stream的中间值,方便我们的调试。
为什么只作为debug使用呢?我们再看一个例子:
Stream.of("one", "two", "three","four").peek(u -> u.toUpperCase())
.forEach(System.out::println);
上面的例子我们使用peek将element转换成为upper case。然后输出:
one
two
three
four
可以看到stream中的元素并没有被转换成大写格式。
再看一个map的对比:
Stream.of("one", "two", "three","four").map(u -> u.toUpperCase())
.forEach(System.out::println);
输出:
ONE
TWO
THREE
FOUR
可以看到map是真正的对元素进行了转换。
当然peek也有例外,假如我们Stream里面是一个对象会怎么样?
@Data
@AllArgsConstructor
static class User{
private String name;
}
List<User> userList=Stream.of(new User("a"),new User("b"),new User("c"))
.peek(u->u.setName("kkk"))
.collect(Collectors.toList());
log.info("{}",userList);
输出结果:
10:25:59.784 [main] INFO com.flydean.PeekUsage - [PeekUsage.User(name=kkk), PeekUsage.User(name=kkk), PeekUsage.User(name=kkk)]
我们看到如果是对象的话,实际的结果会被改变。
为什么peek和map有这样的区别呢?
我们看下peek和map的定义:
Stream<T> peek(Consumer<? super T> action)
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
peek接收一个Consumer,而map接收一个Function。
Consumer是没有返回值的,
而Function是有返回值的,
这就是为什么peek String不会发生变化而peek Object会发送变化的原因。
// 转换为树结构
List<ResourceOutModel> resourceTree =
resourceList.stream()
.filter(i -> i.getPid() == null) //过滤不符合的数据
//逐个元素设置 子节点,子节点的 子节点,递归
.peek(i -> i.setChildren(getChildren(i, resourceList)))
.collect(Collectors.toList());
/**
* 递归获取子节点
*
* @param node 节点对象
* @param list 列表对象
* @return 树对象
*/
private List<ResourceOutModel> getChildren(ResourceOutModel node, List<ResourceOutModel> list) {
return list.stream()
//当 参数的节点 == 循环的父节点(说明参数的节点 找到儿子了)
.filter(i -> node.getId().equals(i.getPid()))
//再次递归设置调用
.peek(i -> i.setChildren(getChildren(i, list)))
.collect(Collectors.toList());
}
public class ResourceOutModel {
private Long id;
private Long pid;
private List<ResourceOutModel> children;
}
*Java*中将*List转为树*形*结构*的三种方法:https://www.csdn.net/tags/MtzaAgwsMzkzMDAtYmxvZwO0O0OO0O0O.html
Mapper文件
常规写法
Stream流处理
使用SQL
oracle 使用 start with connect by prior
mysql使用 普通sql 或 自定义函数
核心都是:find_in_set 和 concat 函数
另一种树查询是:
<!--自定义ResultMap -->
<resultMap id="OrganizationListResultMap" type="com.car2p.accountsystem.model.b.orga.OrganizationOutModel">
<id column="id" jdbcType="BIGINT" property="id"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="busi_id" jdbcType="BIGINT" property="busiId"/>
<result column="super_orga" jdbcType="BIGINT" property="superOrga"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="status" jdbcType="TINYINT" property="status"/>
<result column="level" jdbcType="TINYINT" property="level"/>
</resultMap>
<!--树形查询-->
<select id="getOrganizationList" resultMap="OrganizationListResultMap"
parameterType="com.car2p.accountsystem.model.b.orga.OrganizationInModel">
<!-- 最外层在套查询,筛选条件-->
SELECT * FROM (
select id,create_time,name,status,level,busi_id,super_orga from (
select t1.id,t1.create_time,t1.name,t1.status,t1.level,t1.busi_id,t1.super_orga,
<!-- 如果父ID在pids中查询,查到就执行拼接 或者 用ID在pids中查询,查不到就ischild赋值为0。最终结果赋值为ischild字段。
如果parent_id 在@pid中,则将@pid 里面再加上parent_id,按行依次执行 -->
if(find_in_set(super_orga, @pids) > 0, @pids := CONCAT(@pids,',', id), 0) as ischild
from (
<!-- 最内层是 条件查询,名字是模糊查询,创建时间 时间段查询。最后排序,现在是按照了 父类和ID -->select
id,create_time,name,status,level,busi_id,super_orga from orga t
where t.delete_flag = -1
order by super_orga, id
) t1,
<!-- @pids 初值赋值 --> (select @pids := #{organizationId,jdbcType=BIGINT} ) t2
) t3
where ischild != 0
<!-- 1查自己和子组织 2,只查子组织(不需要下面这个或者情况)-->
<if test="onlyChildren == 1">
or id = #{organizationId,jdbcType=BIGINT}
</if>
) ta
where 1=1
<if test="( organizationName != null)and( organizationName != '')">
AND ta.name LIKE CONCAT(CONCAT('%', #{organizationName,jdbcType=VARCHAR}),'%')
</if>
<if test="( createTimeStart != null)and( createTimeEnd != null)">
AND (ta.create_time between #{createTimeStart,jdbcType=TIMESTAMP} and #{createTimeEnd,jdbcType=TIMESTAMP})
</if>
</select>
<!-- 保存的说明:
or IF(id=@pids,1,0)
AS ischild 加入这样的代码也行,为什么行,当Id= pids (第一次),就赋值为1,否则就赋值为0 ,
肯定每次执行的第一次,就赋值为1了。
下面的 这个SQL的说明:假如全表数据是:
id pid
1 0
2 1
3 2
4 6
我们想输入的查询是1,(加上上面这个代码才执行1),现在是第一次为true是 2的 父ID是1,刚好,
FIND_IN_SET(org_parent_id为1, @pids为1)
执行拼接。 1,2 。此时pids变成 1,2
@pids := CONCAT(@pids, ',', id)
下次 ID,变成3, id 3的 父类是 2, 2 在PID 1,2 中
下下次 pids变成 1,2,3,但是后面的数据 没有符合的,符合的只有ID 2,3 (想要1 可以用or IF(id=@pids,1,0) 或者 下面的sql )
树查询解释,从新开始
1,oracle 使用 start with connect by prior
下递归,包含自己:
select * from dept start with id='1001' connet by prior id=pid;
如改成上递归,只需要 prior后面互换:pid=id;
如向下递归,不包含自己只需 把id改成pid
2,mysql使用 普通sql 或 自对应函数
一,sql查1下的所有子节点
select id from (
select t1.id,
if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids,',', id), 0) as ischild
from (
select id,parent_id from menu t where t.status = 1 order by parent_id, id
) t1,
(select @pids := 1) t2
) t3 where ischild != 0
如果包含子节点,sql后加入 or id=1
1,t2是@pids赋值,
2,t1是全表查,根据 父id和子id排序(目的是 使有序的循环)
如:t1 前的sql 会执行出这样的结果。第一列是id,第二类父id
1 0
11 1
12 1
111 11
3,find_in_set(parent_id, @pids) > 0 ,第一次执行 pids=1,id为1的 父id为0,0不再1中,执行为 假。
第二次 pids =1,id为 11的 父id为1,1在1中,执行为真。
4,使用 id为 11,执行下列,变成:
if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids,',', id), 0)
pids= 有原来的1,拼接成 1,11 (这次执行的id)
5, 执行到 id= 12,12的 父id为1,依然拼接到后面, ischild 的结果为
1 0
11 1,11
12 1,11,12
111 1,11,12,111
6,此时判断 ischild != 0 即可得到 子节点。
二,使用函数
CREATE FUNCTION `GET_CHILD_NODE`(rootId varchar(100))
RETURNS varchar(2000)
BEGIN
DECLARE str varchar(2000);
DECLARE cid varchar(100);
SET str = '$';
SET cid = rootId;
WHILE cid is not null DO
SET str = concat(str, ',', cid);
SELECT group_concat(id) INTO cid FROM tree where FIND_IN_SET(pid, cid);
END WHILE;
RETURN str;
END
使用:select * from tree where FIND_IN_SET(id, GET_CHILD_NODE(2))
总体思路为:GET_CHILD_NODE 函数,得到 当前和 所有子节点
在 FIND_IN_SET(id, 当前 和 所有子节点),所有需要的数据即取出来。
函数说明:
1,str = '$' 初值,无意义, 最终返回的是 str
2,cid 先赋值 参数传递的,如例子是2
3,进入循环 str = concat(str, ',', cid); ,str先把 cid 的2 给拼接上
4,执行 SELECT group_concat(id) FROM tree where FIND_IN_SET(pid, '2')
得到:所有 父id是2 的数据,取id,写入 INTO cid
5,只要得到的不是null,循环继续,如此时得到的是3,cid为3
6,在执行str 拼接,str已经是 $,2 拼接3 为 $,2,3
7,此时在执行 SELECT FIND_IN_SET(pid, '3'),如4的pid是4, 4会筛序出来。
8,str会继续拼接4,$,2,3,4 最终返回。
9,使用这个函数 FIND_IN_SET(id,'$,2,3,4') ,id是2,3,4 的都会查出来,2是自己输入的参数。
-->
<resultMap id="nestedCategory" type="com.baizhi.mybatisplus.entity.vo.ProductCategoryVo">
<id property="id" column="id"/>
<result property="title" column="title"/>
<result property="sort" column="sort"/>
<collection property="children"
ofType="com.baizhi.mybatisplus.entity.vo.ProductCategoryVo"
select="selectNestedListByParentId"
column="id" />
</resultMap>
<select id="selectNestedListByParentId" resultMap="nestedCategory">
select id,sort,title from tbl_product_category where parent_id = ${parent_id}
</select>
https://blog.csdn.net/qq_31564573/article/details/117868011