背景:在平时的开发中,我们时常会遇到下列场景

  1. 公司的组织架构的数据存储与展示
  2. 文件夹层级的数据存储与展示
  3. 评论系统中,父评论与诸多子评论的数据存储与展示
  4. ......

对于这种有层级的结构化数据,就像是一棵一样。在关系型数据库中,通常将一个个的节点信息存储到表中,通过一个字段(例如,pid),指向其父节点。而在数据展示的时候,我们又希望它是呈现层级的,例如:

id  name        pid
1 总公司 -1
2 上海分公司 1
3 浙江分公司 1
4 闵行区分公司 2
5 嘉兴分公司 3 {
"id": 1,
"name": "总公司",
"pid": -1,
"branch":
[
{
"id": 2,
"name": "上海分公司",
"pid": 1,
"branch":
[
{
"id": 4,
"name": "闵行区分公司",
"pid": 2,
"branch":
[]
}
]
},
{
"id": 3,
"name": "浙江分公司",
"pid": 1,
"branch":
[
{
"id": 5,
"name": "嘉兴分公司",
"pid": 3,
"branch":
[]
}
]
}
]
}

所以,本文的主要内容就是提供几种方案,实现这两类数据的转换方式。

内容导览


存储树的表结构

如何在一张数据库表中表示一颗树结构中的所有节点信息,这里有一个示例:

DROP TABLE IF EXISTS zj_city;
CREATE TABLE zj_city (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) COMMENT '节点名称',
pid int NOT NULL COMMENT '父节点', create_time DATETIME DEFAULT now() COMMENT '创建时间: 年-月-日 时:分:秒',
update_time DATETIME DEFAULT now() ON UPDATE now() COMMENT '更新时间',
is_deleted BIT DEFAULT 0 COMMENT '是否删除:0-false-未删除;1-true-已删除',
PRIMARY KEY (id)
)COMMENT '浙江城市'; INSERT INTO zj_city(name, pid) VALUES
('浙江省',0),
('金华市',1),
('嘉兴市',1),
('杭州市',1),
('宁波市',1); INSERT INTO zj_city(name, pid) VALUES
('下城区',4),
('钱塘区',4),
('西湖区',4),
('上城区',4); INSERT INTO zj_city(name, pid) VALUES
('南湖区',3),
('秀洲区',3),
('桐乡市',3),
('平湖市',3),
('海宁市',3); INSERT INTO zj_city(name, pid) VALUES
('梧桐街道',12),
('凤鸣街道',12),
('龙翔街道',12),
('崇福镇',12),
('乌镇镇',12),
('高桥镇',12),
('河山镇',12),
('濮院镇',12); SELECT * from zj_city;

扁平List转树形List

应用场景

  • 公司组织结构
  • 省市级
  • 评论系统中,父评论与诸多子评论
  • 其他层级展示的数据

双层for

主要思想:外层循环-找父节点;内层循环-找子节点;因为每个元素都会找一遍,所有最终得到完整的树

import com.alibaba.fastjson.JSON;
import com.ks.boot.entity.CityEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.ArrayList;
import java.util.List; public class TreeListDemo {
List<CityEntity> cityEntities;
/**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
@BeforeEach
public void init() {
cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1},\n" +
"{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
"{\"id\":5,\"name\":\"桐乡\",\"pid\":3},\n" +
"{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
"{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
"{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
"{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
"{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
} @Test
public void testList2Tree() {
List<CityEntity> resultTree = list2Tree(this.cityEntities);
System.out.println(JSON.toJSONString(resultTree));
} /**
* 双层for,List转Tree
* 主要思想:外层循环-找父节点;内层循环-找子节点;因为每个元素都会找一遍,所有最终得到完整的树
* 时间复杂度:N^2;空间复杂度:N
*/
public List<CityEntity> list2Tree(List<CityEntity> cityEntities) {
List<CityEntity> resultCities = new ArrayList<>();
for (CityEntity city : cityEntities) {
if(0 == city.getPid()) { //根节点、顶级节点,直接放入最终返回结果的List
resultCities.add(city);
}
for (CityEntity curCity : cityEntities) { //根据当前city找它的子节点
if(city.getId().equals(curCity.getPid())) {
if(city.getSubCityList() == null) { //还没有任何子节点,new一个空的放进去
city.setSubCityList(new ArrayList<>());
}
city.getSubCityList().add(curCity);
}
}
} return resultCities;
}
} public class CityEntity {
private Long id;
private String name;
private Long pid; private List<CityEntity> subCityList; getter/setter
}

递归

主要思想:获取所有根节点、顶级节点,再从List中查找根节点的子节点;

import com.alibaba.fastjson.JSON;
import com.ks.boot.entity.CityEntity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.ArrayList;
import java.util.List; public class TreeListDemo {
List<CityEntity> cityEntities;
/**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
@BeforeEach
public void init() {
cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1},\n" +
"{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
"{\"id\":5,\"name\":\"桐乡\",\"pid\":3},\n" +
"{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
"{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
"{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
"{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
"{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
} /**
* 递归,List转Tree
* 主要思想:获取所有根节点、顶级节点,再从List中查找根节点的子节点;
* 时间复杂度:N*(1+N)/2,O(N^2),因为递归方法中,最好是List的第一元素就是要找的子节点,最坏是
* List的最后一个元素是子节点
*/
@Test
public void testList2Tree() {
List<CityEntity> resultCities = new ArrayList<>();
for (CityEntity city : cityEntities) {
if(0 == city.getPid()) { //获取所有根节点、顶级节点,再根据根节点进行递归
CityEntity topCity = findChild(cityEntities, city); //此时的topCity已经包含它的所有子节点
resultCities.add(topCity);
}
} System.out.println(JSON.toJSONString(resultCities));
} /**
*
* @param cityEntities 在那个里面找
* @param curCity 找谁的子节点
* @return curCity的子节点
*/
public CityEntity findChild(List<CityEntity> cityEntities, CityEntity curCity) {
for (CityEntity city : cityEntities) {
if(curCity.getId().equals(city.getPid())) {
if(null == curCity.getSubCityList()) {
curCity.setSubCityList(new ArrayList<>());
}
CityEntity subChild = findChild(cityEntities, city); //每次递归,都从头开始查找有没有city的子节点
curCity.getSubCityList().add(subChild);
}
}
return curCity;
} } public class CityEntity {
private Long id;
private String name;
private Long pid; private List<CityEntity> subCityList; getter/setter
}

转换为Map

主要思想

  • 在双层for的解法中,由于内层for也需要遍历以便List,造成时间复杂度上身为平方级
  • 如果内层for不需要遍历完整的List,而是事先预处理到Map中,寻找时直接从Map中获取,则时间复杂度降为LogN
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; public class TreeListDemo {
List<CityEntity> cityEntities;
/**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
@BeforeEach
public void init() {
cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1},\n" +
"{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
"{\"id\":5,\"name\":\"桐乡\",\"pid\":3},\n" +
"{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
"{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
"{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
"{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
"{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
} /**
* 在双层for的解法中,由于内层for也需要遍历以便List,造成时间复杂度上身为平方级
* 如果内层for不需要遍历完整的List,而是事先预处理到Map中,寻找时直接从Map中获取,则时间复杂度降为LogN
*/
@Test
public void list2tree() {
//收集每个PID下的节点为Map
Map<Long, List<CityEntity>> cityMapByPid = cityEntities.stream().collect(Collectors.groupingBy(CityEntity::getPid)); List<CityEntity> resultCityList = new ArrayList<>();
for (CityEntity city : cityEntities) {
if(0 == city.getPid()) { //根节点、顶点
resultCityList.add(city);
} List<CityEntity> citiesByPid = cityMapByPid.get(city.getId());
if(null != citiesByPid && citiesByPid.size() > 0) { //有子节点
if(null == city.getSubCityList()) {
city.setSubCityList(new ArrayList<>());
}
city.getSubCityList().addAll(citiesByPid); //塞入
}
} System.out.println(JSON.toJSONString(resultCityList));
} /**
* 简化写法:在收集到Map时,对于没有子节点的节点,创建一个空的塞入到Map中
*/
@Test
public void list2tree4Simple() {
List<CityEntity> resultCityList = new ArrayList<>(); //保存每个PID下的子节点
Map<Long, List<CityEntity>> cityMapByPid = new HashMap<>();
for (CityEntity city : cityEntities) { //收集每个PID下的子节点
//获取当前PID对应的子节点List,如果没有则创建一个空的List塞入
//这个设计得很巧妙
List<CityEntity> children = cityMapByPid.getOrDefault(city.getPid(), new ArrayList<>());
children.add(city); //插入当前元素
cityMapByPid.put(city.getPid(), children);
} for (CityEntity city : cityEntities) {
if(0 == city.getPid()) { //根节点、顶点
resultCityList.add(city);
}
city.setSubCityList(cityMapByPid.get(city.getId()));
} System.out.println(JSON.toJSONString(resultCityList));
}
}

主要思想

  • 收集根节点、顶级节点,存入resultList,并且压栈
  • 循环出栈,栈元素Cur
    • 找Cur的所有子元素为child
    • 如果child不为空,则再压入栈中。这一步的目的是,再一次找child的子元素
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.*;
import java.util.stream.Collectors; public class TreeListDemo {
List<CityEntity> cityEntities;
/**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
@BeforeEach
public void init() {
cityEntities = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0},\n" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1},\n" +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1},\n" +
"{\"id\":4,\"name\":\"南湖\",\"pid\":3},\n" +
"{\"id\":5,\"name\":\"桐乡\",\"pid\":3},\n" +
"{\"id\":6,\"name\":\"余杭\",\"pid\":2},\n" +
"{\"id\":7,\"name\":\"西湖\",\"pid\":2},\n" +
"{\"id\":8,\"name\":\"云南\",\"pid\":0},\n" +
"{\"id\":9,\"name\":\"昆明\",\"pid\":8},\n" +
"{\"id\":10,\"name\":\"昭通\",\"pid\":8}]", CityEntity.class);
} /**
* 主要思想:
* 收集根节点、顶级节点,存入resultList,并且压栈
* 循环出栈,栈元素Cur
* 找Cur的所有子元素为child
* 如果child不为空,则再压入栈中。这一步的目的是,再一次找child的子元素
* 时间复杂度:N(过滤出所有跟节点) + 常数(出栈) * N(遍历List找当前节点的子元素)
*/
@Test
public void list2tree() {
List<CityEntity> resultCityList = new ArrayList<>(); Stack<CityEntity> stack = new Stack<>();
resultCityList = cityEntities.stream().filter(ele -> 0 == ele.getPid()).collect(Collectors.toList());
stack.addAll(resultCityList); //根节点、顶点入栈 while(!stack.isEmpty()) {
CityEntity curCity = stack.pop();
List<CityEntity> child = cityEntities.stream().filter(ele -> curCity.getId().equals(ele.getPid())).collect(Collectors.toList());
if(!child.isEmpty()) { //这一步处理的原因是:当没有子元素,不显示该个字段。流处理后没有元素只会返回空List,不会返回null
curCity.setSubCityList(child);
}
if(!child.isEmpty()) {
stack.addAll(child);
}
} System.out.println(JSON.toJSONString(resultCityList));
}
}

树形List转扁平List

递归

主要思想:遍历树节点,一个树节点如果有子树,则再次递归此子树,直到没有子树为止

import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.ArrayList;
import java.util.List; /**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
public class ListTreeDemo {
List<CityEntity> treeList; @BeforeEach
public void init() {
treeList = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0,\"subCityList\":[" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1,\"subCityList\":[{\"id\":6,\"name\":\"余杭\",\"pid\":2},{\"id\":7,\"name\":\"西湖\",\"pid\":2}]}," +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1,\"subCityList\":[{\"id\":4,\"name\":\"南湖\",\"pid\":3},{\"id\":5,\"name\":\"桐乡\",\"pid\":3}]}]}," +
"{\"id\":8,\"name\":\"云南\",\"pid\":0,\"subCityList\":[{\"id\":9,\"name\":\"昆明\",\"pid\":8},{\"id\":10,\"name\":\"昭通\",\"pid\":8}]}]", CityEntity.class);
} @Test
public void tree2list() {
List<CityEntity> resList = new ArrayList<>(); //这一层for的目的是:遍历根节点
for (CityEntity city : treeList) {
reversion(city,resList);
}
System.out.println(JSON.toJSONString(resList));
}
public void reversion(CityEntity curNode, List<CityEntity> resList) {
resList.add(beanCopy(curNode)); List<CityEntity> subCityList = curNode.getSubCityList();
if(subCityList != null && !subCityList.isEmpty()) {
for (CityEntity city : subCityList) { //递归寻找子节点的子节点们
reversion(city, resList);
}
} //递归的出口就是subCityList为null或者empty
} private CityEntity beanCopy(CityEntity source) {
CityEntity res = new CityEntity();
res.setId(source.getId());
res.setName(source.getName());
res.setPid(source.getPid());
return res;
}
}

主要思想

  1. 依次遍历树形List,当前节点为Cur

    1. 将Cur收集到某个存储结果的List
    2. 如果Cur有子树,压入某个栈中
  2. 依次弹出栈元素,当前弹出的元素为StackSubTree
    1. 如果StackSubTree还有子树,继续压栈
    2. 如果StackSubTree没有子树,则放入结果List
import com.alibaba.fastjson2.JSON;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import java.util.ArrayList;
import java.util.List;
import java.util.Stack; /**
* id name pid
* 1 浙江 0
* 2 杭州 1
* 3 嘉兴 1
* 4 南湖 3
* 5 桐乡 3
* 6 余杭 2
* 7 西湖 2
* 8 云南 0
* 9 昆明 8
* 10 昭通 8
*/
public class ListTreeDemo {
List<CityEntity> treeList; @BeforeEach
public void init() {
treeList = JSON.parseArray("[{\"id\":1,\"name\":\"浙江\",\"pid\":0,\"subCityList\":[" +
"{\"id\":2,\"name\":\"杭州\",\"pid\":1,\"subCityList\":[{\"id\":6,\"name\":\"余杭\",\"pid\":2},{\"id\":7,\"name\":\"西湖\",\"pid\":2}]}," +
"{\"id\":3,\"name\":\"嘉兴\",\"pid\":1,\"subCityList\":[{\"id\":4,\"name\":\"南湖\",\"pid\":3},{\"id\":5,\"name\":\"桐乡\",\"pid\":3}]}]}," +
"{\"id\":8,\"name\":\"云南\",\"pid\":0,\"subCityList\":[{\"id\":9,\"name\":\"昆明\",\"pid\":8},{\"id\":10,\"name\":\"昭通\",\"pid\":8}]}]", CityEntity.class);
} /**
* 1. 依次遍历树形List,当前节点为Cur
* a) 将Cur收集到某个存储结果的List
* b) 如果Cur有子树,压入某个栈中
* 2. 依次弹出栈元素,当前弹出的元素为StackSubTree
* a) 如果StackSubTree还有子树,继续压栈
* b) 如果StackSubTree没有子树,则放入结果List
*/
@Test
public void tree2list() {
List<CityEntity> resList = new ArrayList<>(); Stack<List<CityEntity>> stack = new Stack<>(); for (CityEntity curCity : treeList) {
resList.add(beanCopy(curCity));
if (curCity.getSubCityList() != null && !curCity.getSubCityList().isEmpty()) {
stack.push(curCity.getSubCityList());
}
} while (!stack.isEmpty()) {
List<CityEntity> subTree = stack.pop();
for (CityEntity city : subTree) {
if (city.getSubCityList() != null && !city.getSubCityList().isEmpty()) {
stack.push(city.getSubCityList());
} else {
resList.add(beanCopy(city));
}
}
} System.out.println(JSON.toJSONString(resList));
} private CityEntity beanCopy(CityEntity source) {
CityEntity res = new CityEntity();
res.setId(source.getId());
res.setName(source.getName());
res.setPid(source.getPid());
return res;
}
}

"树形List"与"扁平List"互转(Java实现)的更多相关文章

  1. .net互转java 转行必备

    .net与java其实是差不多的语言,学习起来只需要弄清楚差异及查库的方法,转起来还是很快的 以下列出几点,希望能给正在转行的你一些帮助 1,java与c#语言超详细对比 http://www.har ...

  2. 树形结构数据存储方案的选择和java list转tree

    树形结构数据存储方案 Adjacency List:每一条记录存parent_idPath Enumerations:每一条记录存整个tree path经过的node枚举Nested Sets:每一条 ...

  3. 2019 三七互娱java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.三七互娱等公司offer,岗位是Java后端开发,因为发展原因最终选择去了三七互娱,入职一年时间了,也成为了面 ...

  4. 最新 三七互娱java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.三七互娱等10家互联网公司的校招Offer,因为某些自身原因最终选择了三七互娱.6.7月主要是做系统复习.项目复盘.Leet ...

  5. js树形数据结构的扁平化

    前面我们封装了一维数组(具备树形结构相关属性)处理成树形结构的方法:https://www.cnblogs.com/coder--wang/p/15013664.html 接下来我们来一波反向操作,封 ...

  6. 牛客网程序员面试金典:1.1确定字符互异(java实现)

    问题描述: 请实现一个算法,确定一个字符串的所有字符是否全都不同.这里我们要求不允许使用额外的存储结构. 给定一个string iniString,请返回一个bool值,True代表所有字符全都不同, ...

  7. js格式化树形数据(扁平化数据)

    需求: 1.把如下数据按照parent_id等于id的规则建立父子关系 2.同一层级的数组按照order升序 [ { "id": 1, "name": &quo ...

  8. 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转 JAVA

    package com.asiabasehk.cgg.util;   /**火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转  * Created by macremote on 1 ...

  9. JSON字符串和java对象的互转【json-lib】

    在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好, ...

  10. json字符串与java对象互转

    在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好, ...

随机推荐

  1. 全新TI AM62xx系列核心板上市,小小身板蕴藏巨大势能!

    2011年TI推出AM335x,成为了此后市场上最受欢迎的通用工业级ARM处理器,并广泛应用于工业HMI, 医疗电子,机器人,能源,汽车等领域.随着工业4.0的发展,HMI人机交互.工业工控.医疗等领 ...

  2. Undelivered Mail Returned to Sender

    电子邮件是使用电子邮件地址application@sample.com从Application发送的. 出于业务原因我们无法在此应用程序中更新/删除无效的外部电子邮件地址,因此响应出站电子邮件会生成许 ...

  3. svn备份迁移

    参考链接: SVN版本库的迁移 dump的详细使用 https://www.iteye.com/blog/tdcq-1684344 svn备份与还原_脚本_(dump命令)

  4. 对于Python中RawString的理解(引用)

    对于Python中RawString的理解 总结 1.'''作用: 可以表示 "多行注释" ."多行字符串" ."其内的单双引号不转义" 2 ...

  5. 函数XLOOKUP

    这个公式非OFFICE 365用户需要选中执行范围后 按Ctrl+Shift+Enter三键 (因为不支持公式溢出) XLOOKUP函数的基本结构是: =XLOOKUP(lookup_value,lo ...

  6. .NET周报 【3月第2期 2023-03-12】

    国内文章 ASP.NET Core中如何限制响应发送速率(不是调用频率) https://www.cnblogs.com/coredx/p/17195492.html ASP.NET Core中有很多 ...

  7. Spring Boot笔记--Spring Boot相关介绍+快速入门

    相关介绍 简化了Spring开发,避免了Spring开发的繁琐过程 提供了自动配置.起步依赖.辅助功能 快速入门 结果呈现: 相关过程: helloController.java package or ...

  8. 研发效能负责人/研发效能1号位 |DevOps负责人

    想要做好业务,老板们除了要梳理好公司级别的业务目标,公司的组织架构,还要搭个有产出的班子,也就是找负责人.建团队,让组织架构充实起来.搭班子最重要的就是把负责人找到,就是团队1号位的人.本文主要讲团队 ...

  9. 了解CSS Module作用域隔离原理

    CSS Module出现的背景 我们知道,Javascript发展到现在出现了众多模块化规范,比如AMD.CMD. Common JS.ESModule等,这些模块化规范能够让我们的JS实现作用域隔离 ...

  10. java数组使用、Arrays类使用 、排序方法

    数组使用 数组的基本使用: package charpter4; public class ArrayDemo2 { public static void main(String[] args) { ...