"树形List"与"扁平List"互转(Java实现)
背景:在平时的开发中,我们时常会遇到下列场景
- 公司的组织架构的数据存储与展示
- 文件夹层级的数据存储与展示
- 评论系统中,父评论与诸多子评论的数据存储与展示
- ......
对于这种有层级的结构化数据,就像是一棵树一样。在关系型数据库中,通常将一个个的节点信息存储到表中,通过一个字段(例如,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;
}
}
栈
主要思想
- 依次遍历树形List,当前节点为Cur
- 将Cur收集到某个存储结果的List
- 如果Cur有子树,压入某个栈中
- 依次弹出栈元素,当前弹出的元素为StackSubTree
- 如果StackSubTree还有子树,继续压栈
- 如果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实现)的更多相关文章
- .net互转java 转行必备
.net与java其实是差不多的语言,学习起来只需要弄清楚差异及查库的方法,转起来还是很快的 以下列出几点,希望能给正在转行的你一些帮助 1,java与c#语言超详细对比 http://www.har ...
- 树形结构数据存储方案的选择和java list转tree
树形结构数据存储方案 Adjacency List:每一条记录存parent_idPath Enumerations:每一条记录存整个tree path经过的node枚举Nested Sets:每一条 ...
- 2019 三七互娱java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.三七互娱等公司offer,岗位是Java后端开发,因为发展原因最终选择去了三七互娱,入职一年时间了,也成为了面 ...
- 最新 三七互娱java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.三七互娱等10家互联网公司的校招Offer,因为某些自身原因最终选择了三七互娱.6.7月主要是做系统复习.项目复盘.Leet ...
- js树形数据结构的扁平化
前面我们封装了一维数组(具备树形结构相关属性)处理成树形结构的方法:https://www.cnblogs.com/coder--wang/p/15013664.html 接下来我们来一波反向操作,封 ...
- 牛客网程序员面试金典:1.1确定字符互异(java实现)
问题描述: 请实现一个算法,确定一个字符串的所有字符是否全都不同.这里我们要求不允许使用额外的存储结构. 给定一个string iniString,请返回一个bool值,True代表所有字符全都不同, ...
- js格式化树形数据(扁平化数据)
需求: 1.把如下数据按照parent_id等于id的规则建立父子关系 2.同一层级的数组按照order升序 [ { "id": 1, "name": &quo ...
- 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转 JAVA
package com.asiabasehk.cgg.util; /**火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转 * Created by macremote on 1 ...
- JSON字符串和java对象的互转【json-lib】
在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好, ...
- json字符串与java对象互转
在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好, ...
随机推荐
- c输入的缓冲区
作业题:输入两个整数(12和37),从键盘输入'A'和'a'时,输出两个数中的较大数:从键盘输入'B'和'b'时,输出两个数中的较小数. int a; char c; scanf("%d&q ...
- What is Weight Lifting?
Weight lifting is the process of lifting items of great mass in order to increase the muscle size an ...
- 1.3 ODBC 部署监控数据库
一.安装ODBC 来自为知笔记(Wiz)
- burpsuite 设置文字大小、抓取https数据头
设置文字大小 burpsuite安装好后,有些时候文字非常的小,看的眼睛直接痛死. 找到 User options -> Display 其中 User Interface -> Font ...
- return、break与continue的区别
前言 在上一篇文章中,壹哥给大家介绍了while.do-while两种循环结构,并且给大家总结了两种循环的区别.实际上,我们在利用循环执行重复操作的过程中,还存在着另一个需求:如何中止,或者说提前结束 ...
- Java BIO,NIO,AIO
一丶IO模型&Java IO Unix为程序员提供了以下5种基本的io模型: blocking io: 阻塞io nonblocking io: 非阻塞io I/O multiplexing: ...
- 你绝对没想到的GPT的底层意义
学会说话才是完整的人 有种说法在民间流传已久,在某些非洲部落中,孩子出生后往往会被称作"小人"或者"半个人",直到他们能够进行语言的交流才被认为是完全的人.这是 ...
- [Linux]常用命令之【tar/zip/unzip/gzip/gunzip】
1 tar .tar与.gz有什么联系与区别? .tar 只是进行打包,并没有压缩. 则: 用tar-cvf进行打包 用tar-xvf进行解包. .tar.gz 是既打包又压缩 ,则: tar –cz ...
- [Git]解决GIT冲突问题:git pull failed
1 文由 花了很长时间一次性修改了项目的一大堆文件,准备最后git pull同步一下本地仓库代码,再一次性git commit,git push新代码的. but天不遂人愿,git pull时产生冲突 ...
- day05-SpringCloud Eureka-服务注册与发现02
SpringCloud Eureka-服务注册与发现02 3.搭建EurekaServer集群-实现负载均衡&故障容错 3.1为什么需要集群EurekaServer? 微服务RPC远程服务调用 ...