实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
文章目录
申明
首先说明一下,这是一道面试题。介于时间关系这道题只能算是解决了一半。
一、问题描述
//实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
//输入
List<String> pathList = Arrays.asList(
"/etc/hosts",
"/etc/kubernetes/ssl/certs",
"/root"
);
//输出
/**
{
"etc":{
"hosts":{},
"kubernetes":{
"ssl":{
"certs":{}
}
}
},
"root":{}
}
二、实现思路
1、按照每一行的路径记录 / 的位置,得到一个二维数组。
统计一行中字符串中 / 的位置 ,得到一维数组。
//统计一行字符串中 / 的位置
private static List<Integer> countNum(String path){
List<Integer> rowCount = new ArrayList<Integer>() ;
if (!path.isEmpty()){
char[] chars = path.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '/'){
rowCount.add(i);
}
}
}
return rowCount;
}
统计多行字符串中 / 的位置 ,得到二维数组。
//统计 有多少行 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
List<List<Integer>> colCount = new ArrayList<List<Integer>>();
for (int i = 0; i < pathList.size(); i++) {
List<Integer> rowCount = countNum(pathList.get(i));
Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
mapList.add(rowElementMap);
colCount.add(rowCount);
}
2、由第1步的 / 位置 数组 进行字符串递归截串,注意 /root 这种情况即可。
这里解释下为什么递归:
"/etc/hosts",
"/etc/kubernetes/ssl/certs",
"/root"
每一个路径都可以看成是 /文件夹名称 这种问题处理。
截串形式为:
/etc/kubernetes/ssl/certs
/kubernetes/ssl/certs
/ssl/certs
/certs
因此,每次需要重新获取path
int right = rowCount.get(1);
String pathTemp = path.substring(right);
递归实现
private static Map<String, Map> rowElementMap(String path){
List<Integer> rowCount = countNum(path);
int left = rowCount.get(0)+1;
if (rowCount.size() == 1){
String rowKey = path.substring(left);
HashMap<String, Map> rowMap = new HashMap<>();
rowMap.put(rowKey, new HashMap());
return rowMap;
}else {
int right = rowCount.get(1);
String rowKey = path.substring(left, right);
String pathTemp = path.substring(right);
HashMap<String, Map> rowMap = new HashMap<>();
//注意这里的value,递归获取map
rowMap.put(rowKey, rowElementMap(pathTemp));
return rowMap;
}
}
三、源码
方法一、返回单个map的源代码
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import java.util.*;
/**
* @Description:
* @Author: AustinU
* @CreateTime: 2022/8/18
*/
public class Main {
public static void main(String[] args) {
//实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
List<String> pathList = Arrays.asList(
"/etc/hosts",
"/root",
"/etc/kubernetes/ssl/certs"
);
/**
{
"etc":{
"hosts":{},
"kubernetes":{
"ssl":{
"certs":{}
}
}
},
"root":{}
}
*/
Map<String, Map> resultMap = pathListToMap(pathList);
System.out.println(resultMap);
JSONObject jsonObject = JSONUtil.parseObj(resultMap);
System.out.println(jsonObject);
}
private static Map<String, Map> pathListToMap(List<String> pathList) {
if (pathList.isEmpty()) return null;
if (pathList.size() == 1 && countNum(pathList.get(0)).size() == 1) {
String resKey = pathList.get(0).replaceAll("\\/", "");
HashMap<String,Map> resMap = new HashMap<String, Map>();
resMap.put(resKey, new HashMap<String,Map>());
return resMap;
}else {
List<Map<String, Map>> mapList= new ArrayList<>();
//统计 有多少列 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
List<List<Integer>> colCount = new ArrayList<List<Integer>>();
for (int i = 0; i < pathList.size(); i++) {
List<Integer> rowCount = countNum(pathList.get(i));
Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
mapList.add(rowElementMap);
colCount.add(rowCount);
}
Map<String, Map> resMap = mapList2OneMap(mapList);
return resMap;
}
}
//将多行map合并成同一个map
private static Map<String, Map> mapList2OneMap(List<Map<String, Map>> mapList) {
HashMap<String,Map> resMap = new HashMap<>();
HashMap<String,List<Map<String, Map>>> resListMap = new HashMap<>();
List<Map<String, Map>> resMapList = new ArrayList<>();
if (mapList.isEmpty()) return new HashMap<String, Map>();
if (mapList.size() == 1) return mapList.get(0);
else {
for (int i = 0; i < mapList.size(); i++) {
resMap.putAll(mapList.get(i));
}
return resMap;
}
}
//统计字符串中 / 的位置
private static List<Integer> countNum(String path){
List<Integer> rowCount = new ArrayList<Integer>() ;
if (!path.isEmpty()){
char[] chars = path.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '/'){
rowCount.add(i);
}
}
}
return rowCount;
}
private static Map<String, Map> rowElementMap(String path){
List<Integer> rowCount = countNum(path);
int left = rowCount.get(0)+1;
if (rowCount.size() == 1){
String rowKey = path.substring(left);
HashMap<String, Map> rowMap = new HashMap<>();
rowMap.put(rowKey, new HashMap());
return rowMap;
}else {
int right = rowCount.get(1);
String rowKey = path.substring(left, right);
String pathTemp = path.substring(right);
HashMap<String, Map> rowMap = new HashMap<>();
rowMap.put(rowKey, rowElementMap(pathTemp));
return rowMap;
}
}
}
输出结果:
运行结果放在JSON可视化工具展现如下
和期望结果对比可知,如果map中首次放入的key相同会存在覆盖value的情况。
方法二、返回map的列表的源代码
package ruiqi;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import java.util.*;
/**
* @Description:
* @Author: AustinU
* @CreateTime: 2022/8/18
*/
public class MainReturnMapList {
public static void main(String[] args) {
//实现pathListToMap, 能够将输入的pathList转化为具有层级结构的map类型
List<String> pathList = Arrays.asList(
"/etc/hosts",
"/etc/kubernetes/ssl/certs",
"/root"
);
/**
{
"etc":{
"hosts":{},
"kubernetes":{
"ssl":{
"certs":{}
}
}
},
"root":{}
}
*/
Map<String, List<Map<String, Map>>> resultMap = pathListToMap(pathList);
System.out.println(resultMap);
JSONObject jsonObject = JSONUtil.parseObj(resultMap);
System.out.println(jsonObject);
}
private static Map<String, List<Map<String, Map>>> pathListToMap(List<String> pathList) {
if (pathList.isEmpty()) return null;
if (pathList.size() == 1 && countNum(pathList.get(0)).size() == 1) {
String resKey = pathList.get(0).replaceAll("\\/", "");
HashMap<String,Map> resMap = new HashMap<String, Map>();
resMap.put(resKey, new HashMap<String,Map>());
List<Map<String, Map>> mapList = new ArrayList<>();
mapList.add(resMap);
Map<String, List<Map<String, Map>>> resMapList = new HashMap<>();
resMapList.put(resKey, mapList);
return resMapList;
}else {
List<Map<String, Map>> mapList= new ArrayList<>();
int n = pathList.size();
//统计 有多少列 字符串 包含 多少个list(list存放 / 在字符数组中的位置)
List<List<Integer>> colCount = new ArrayList<List<Integer>>();
for (int i = 0; i < pathList.size(); i++) {
List<Integer> rowCount = countNum(pathList.get(i));
Map<String, Map> rowElementMap = rowElementMap(pathList.get(i));
mapList.add(rowElementMap);
colCount.add(rowCount);
}
Map<String, List<Map<String, Map>>> resMap = mapList2OneMap(mapList);
return resMap;
}
}
//将多行map合并成同一个map
private static Map<String, List<Map<String, Map>>> mapList2OneMap(List<Map<String, Map>> mapList) {
HashMap<String,Map> resMap = new HashMap<>();
HashMap<String,List<Map<String, Map>>> resListMap = new HashMap<>();
List<Map<String, Map>> resMapList = new ArrayList<>();
if (mapList.isEmpty()) return new HashMap<String, List<Map<String, Map>>>();
else {
for (int i = 0; i < mapList.size(); i++) {
for (Map.Entry<String, Map> mapEntry : mapList.get(i).entrySet()) {
if (!resMap.containsKey(mapEntry.getKey())){
resMapList.add(mapEntry.getValue());
resListMap.put(mapEntry.getKey(), resMapList);
}else {
//具有相同key
resMapList.add(mapEntry.getValue());
}
}
}
return resListMap;
}
}
//统计字符串中 有几个 /
private static List<Integer> countNum(String path){
List<Integer> rowCount = new ArrayList<Integer>() ;
if (!path.isEmpty()){
char[] chars = path.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '/'){
rowCount.add(i);
}
}
}
return rowCount;
}
private static Map<String, Map> rowElementMap(String path){
List<Integer> rowCount = countNum(path);
int left = rowCount.get(0)+1;
if (rowCount.size() == 1){
String rowKey = path.substring(left);
HashMap<String, Map> rowMap = new HashMap<>();
rowMap.put(rowKey, new HashMap());
return rowMap;
}else {
int right = rowCount.get(1);
String rowKey = path.substring(left, right);
String pathList = path.substring(right);
HashMap<String, Map> rowMap = new HashMap<>();
rowMap.put(rowKey, rowElementMap(pathList));
return rowMap;
}
}
}
输出结果:
运行结果放在JSON可视化工具展现如下
这里存在的问题是节点信息存在无中生有。
如果大家对 这道题有见解欢迎留言。