查询list转化为tree的两种方式及排序

方式一,数据库查询tree;

MyBatis collection 集合

MyBatis 是数据持久层框架,支持定制化 SQL、存储过程以及高级映射。尤其强大在于它的映射语句,比如高级映射中的 collection 集合。

collection 集合,集合常用的两个场景是集合的嵌套查询、集合的嵌套结果。集合的嵌套结果就是查询结果对应嵌套子对象。这里就是利用 collection 集合嵌套查询树形节点。下面来一一实现。

查询树形节点 Web 案例

创建数据库表

节点表:

CREATE TABLE `node` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `parent_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `parent_id` (`parent_id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COMMENT='节点表'

简单的节点父子关系设计,下面插入几条数据:

INSERT INTO node (name, parent_id) VALUES ('一级节点A', 0);
INSERT INTO node (name, parent_id) VALUES ('一级节点B', 0);
INSERT INTO node (name, parent_id) VALUES ('一级节点C', 0);
INSERT INTO node (name, parent_id) VALUES ('二级节点AA', 1);
INSERT INTO node (name, parent_id) VALUES ('二级节点aa', 1);
INSERT INTO node (name, parent_id) VALUES ('二级节点BB', 2);
INSERT INTO node (name, parent_id) VALUES ('三级级节点AAA', 4);
INSERT INTO node (name, parent_id) VALUES ('三级级节点aaa', 4);
INSERT INTO node (name, parent_id) VALUES ('三级级节点BBB', 6);

重要的还是看 collection 在 xml 的映射实现,NodeMapper.xml 代码如下:

<mapper namespace="org.mybatis.dao.NodeDao">

  <resultMap id="BaseTreeResultMap" type="org.mybatis.domain.Node">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <collection column="id" property="next" javaType="java.util.ArrayList"
                ofType="org.mybatis.domain.Node" select="getNextNodeTree"/>
  </resultMap>

  <resultMap id="NextTreeResultMap" type="org.mybatis.domain.Node">
    <result column="id" property="id"/>
    <result column="name" property="name"/>
    <collection column="id" property="next" javaType="java.util.ArrayList"
                ofType="org.mybatis.domain.Node" select="getNextNodeTree"/>
  </resultMap>

  <sql id="Base_Column_List">
        id, name
    </sql>

  <select id="getNextNodeTree" resultMap="NextTreeResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    FROM node
    WHERE parent_id = #{id}
  </select>

  <select id="getNodeTree" resultMap="BaseTreeResultMap">
    SELECT
    <include refid="Base_Column_List"/>
    FROM node
    WHERE parent_id = 0
  </select>

</mapper>

在 dao 层,我们只调用 getNodeTree 方法,parent_id = 0 代表顶级节点。然后通过 collection 节点继续调用 getNextNodeTree 方法进行循环调用。

<collection column="id" property="next" javaType="java.util.ArrayList"
                ofType="org.mybatis.domain.Node" select="getNextNodeTree"/>

以下是关键的知识点:

  • column 代表会拿父节点 id ,作为参数获取 next 对象
  • javaType 代表 next 对象是个列表,其实可以省略不写
  • ofType 用来区分 JavaBean 属性类型和集合包含的类型
  • select 是用来执行循环哪个 SQL

工程代码地址:https://github.com/JeffLi1993/myabtis-learning-example
工程演示后的结果如图所示:

 
 
 
方式二,内存计算
   方式一查询数据库效率较低,方式二一次查询所有数据,任何用stream流来计算转化为树,建议采用

普通list转树状list

public static List<User> list2tree(List<User> list) {
List<User> result = new ArrayList<>();
Map<Object, User> hash = list.stream().collect(Collectors.toMap(u -> u.getId(), u -> u));
for (User u : list) {
User p = hash.get(u.getParent());
if (p == null) {
result.add(u);
} else {
if (p.getChildren() == null) {
p.setChildren(new ArrayList<>());
}
p.getChildren().add(u);
}
}
return result;
}

树状list转普通list

public static List<User> tree2list(List<User> list) {
List<User> result = new ArrayList<>();
for (User u : list) {
List<User> c = u.getChildren();
result.add(u);
if (!CollectionUtils.isEmpty(c)) {
result.addAll(tree2list(c));
u.setChildren(null);//
}
}
return result;
}

java8 stream多字段排序

使用java8新特性,下面先来点基础的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
List<类> list; 代表某集合
 
//返回 对象集合以类属性一升序排序
 
list.stream().sorted(Comparator.comparing(类::属性一));
 
//返回 对象集合以类属性一降序排序 注意两种写法
 
list.stream().sorted(Comparator.comparing(类::属性一).reversed());//先以属性一升序,结果进行属性一降序
 
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()));//以属性一降序
 
//返回 对象集合以类属性一升序 属性二升序
 
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二));
 
//返回 对象集合以类属性一降序 属性二升序 注意两种写法
 
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二));//先以属性一升序,升序结果进行属性一降序,再进行属性二升序
 
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二));//先以属性一降序,再进行属性二升序
 
//返回 对象集合以类属性一降序 属性二降序 注意两种写法
 
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,升序结果进行属性一降序,再进行属性二降序
 
list.stream().sorted(Comparator.comparing(类::属性一,Comparator.reverseOrder()).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一降序,再进行属性二降序
 
//返回 对象集合以类属性一升序 属性二降序 注意两种写法
 
list.stream().sorted(Comparator.comparing(类::属性一).reversed().thenComparing(类::属性二).reversed());//先以属性一升序,升序结果进行属性一降序,再进行属性二升序,结果进行属性一降序属性二降序
 
list.stream().sorted(Comparator.comparing(类::属性一).thenComparing(类::属性二,Comparator.reverseOrder()));//先以属性一升序,再进行属性二降序<br><br><br>

通过以上例子我们可以发现

1. Comparator.comparing(类::属性一).reversed();

2. Comparator.comparing(类::属性一,Comparator.reverseOrder());

两种排序是完全不一样的,一定要区分开来 1 是得到排序结果后再排序,2是直接进行排序,很多人会混淆导致理解出错,2更好理解,建议使用2

3.注意排序后需要另外一个lis来接收List<xxx> list= Stream.sort(xxx).collect(toList());

class testRun {
    public static void main(String[] args) {
        List<test> testList = new ArrayList<>();
        Date d = DateUtils.now();
        for (int i = 1; i <= 3; i++) {
            test t = new test(i, DateUtils.addDays(d, i));
            testList.add(t);
        }
        for (int i = 1; i <= 3; i++) {
            test t = new test(i, DateUtils.addMonths(d, i));
            testList.add(t);
        }
 
        testList.forEach(o -> {
            System.out.println(o.toString());
        });
        List<test> sort = testList.stream().sorted(Comparator.comparing(test::getState).thenComparing(test::getTime,Comparator.reverseOrder())).collect(toList());
        System.out.println("------------------------------------");
        sort.forEach(o -> {
            System.out.println(o.toString());
        });
 
 
    }
}


参考

链接:https://www.jianshu.com/p/fa20d4bd8ad4

链接:https://blog.csdn.net/qq_41991665/article/details/90484690

 
原文地址:https://www.cnblogs.com/yuluoxingkong/p/11912821.html