目录
Welcome to Code Block’s blog
本篇文章主要介绍了
[Springboot应用开发:工具类整理]
博主广交技术好友,喜欢文章的可以关注一下
一、编写目的
在实际的Springboot应用开发中,有很多类可作为工具类,这些类将实际开发中可能用到的重复性代码进行提取,方便在后续的开发中使用,在这里我对在开发中经常用到的工具类进行整理,方便自己之后查找,同时希望可以帮助到有实现相关功能的朋友。
二、映射工具类
映射工具类主要用于在不同实体类结构之间的转换,经常用于DTO->BO的转换.例:在Controller中接收的Body(DTO)与要存储到数据库中的字段(BO)经常是不同的.这时可以使用该工具类进行转换,使用sourceToTarget对单个实体类或列表进行转换.具体代码如下:
2.1 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2.2 代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 转换工具类
*/
public class ConvertUtils {
private static Logger logger = LoggerFactory.getLogger(ConvertUtils.class);
/**
*
* @param source 原始类实体
* @param target 目标类
* @return 目标类实体
* @param <T> 泛型
*/
public static <T> T sourceToTarget(Object source, Class<T> target){
if(source == null){
return null;
}
T targetObject = null;
try {
targetObject = target.newInstance();
BeanUtils.copyProperties(source, targetObject);
} catch (Exception e) {
logger.error("convert error ", e);
}
return targetObject;
}
/**
*
* @param sourceList 原始类实体列表
* @param target 目标类
* @return 目标类实体列表
* @param <T> 泛型
*/
public static <T> List<T> sourceToTarget(Collection<?> sourceList, Class<T> target){
if(sourceList == null){
return null;
}
List targetList = new ArrayList<>(sourceList.size());
try {
for(Object source : sourceList){
T targetObject = target.newInstance();
BeanUtils.copyProperties(source, targetObject);
targetList.add(targetObject);
}
}catch (Exception e){
logger.error("convert error ", e);
}
return targetList;
}
}
三、日期格式
日期格式工具类主要用于日期格式的转换和日期的计算,例如:从yyyy-MM-dd HH:mm:ss转换为yyyy-MM-dd格式或者从字符串转换为日期格式.具体代码如下:
3.1 依赖
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
3.2 代码
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 日期处理
* @author seaua
*/
public class DateUtils {
/** 时间格式(yyyy-MM-dd) */
public final static String DATE_PATTERN = "yyyy-MM-dd";
/** 时间格式(yyyy-MM-dd HH:mm:ss) */
public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
public static Date parse(String date) {
if(StringUtils.isEmpty(date)){
return null;
}
SimpleDateFormat df = new SimpleDateFormat(DATE_TIME_PATTERN);
try {
return df.parse(date);
} catch (ParseException e) {
e.printStackTrace();
return null;
}
}
/**
* 日期格式化 日期格式为:yyyy-MM-dd
* @param date 日期
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date) {
return format(date, DATE_PATTERN);
}
/**
* 日期格式化 日期格式为:yyyy-MM-dd
* @param date 日期
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
* @return 返回yyyy-MM-dd格式日期
*/
public static String format(Date date, String pattern) {
if(date != null){
SimpleDateFormat df = new SimpleDateFormat(pattern);
return df.format(date);
}
return null;
}
/**
* 日期解析
* @param date 日期
* @param pattern 格式,如:DateUtils.DATE_TIME_PATTERN
* @return 返回Date
*/
public static Date parse(String date, String pattern) {
try {
return new SimpleDateFormat(pattern).parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
/**
* 字符串转换成日期
* @param strDate 日期字符串
* @param pattern 日期的格式,如:DateUtils.DATE_TIME_PATTERN
*/
public static Date stringToDate(String strDate, String pattern) {
if (StringUtils.isBlank(strDate)){
return null;
}
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
return fmt.parseLocalDateTime(strDate).toDate();
}
/**
* 根据周数,获取开始日期、结束日期
* @param week 周期 0本周,-1上周,-2上上周,1下周,2下下周
* @return 返回date[0]开始日期、date[1]结束日期
*/
public static Date[] getWeekStartAndEnd(int week) {
DateTime dateTime = new DateTime();
LocalDate date = new LocalDate(dateTime.plusWeeks(week));
date = date.dayOfWeek().withMinimumValue();
Date beginDate = date.toDate();
Date endDate = date.plusDays(6).toDate();
return new Date[]{beginDate, endDate};
}
/**
* 对日期的【秒】进行加/减
*
* @param date 日期
* @param seconds 秒数,负数为减
* @return 加/减几秒后的日期
*/
public static Date addDateSeconds(Date date, int seconds) {
DateTime dateTime = new DateTime(date);
return dateTime.plusSeconds(seconds).toDate();
}
/**
* 对日期的【分钟】进行加/减
*
* @param date 日期
* @param minutes 分钟数,负数为减
* @return 加/减几分钟后的日期
*/
public static Date addDateMinutes(Date date, int minutes) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMinutes(minutes).toDate();
}
/**
* 对日期的【小时】进行加/减
*
* @param date 日期
* @param hours 小时数,负数为减
* @return 加/减几小时后的日期
*/
public static Date addDateHours(Date date, int hours) {
DateTime dateTime = new DateTime(date);
return dateTime.plusHours(hours).toDate();
}
/**
* 对日期的【天】进行加/减
*
* @param date 日期
* @param days 天数,负数为减
* @return 加/减几天后的日期
*/
public static Date addDateDays(Date date, int days) {
DateTime dateTime = new DateTime(date);
return dateTime.plusDays(days).toDate();
}
/**
* 对日期的【周】进行加/减
*
* @param date 日期
* @param weeks 周数,负数为减
* @return 加/减几周后的日期
*/
public static Date addDateWeeks(Date date, int weeks) {
DateTime dateTime = new DateTime(date);
return dateTime.plusWeeks(weeks).toDate();
}
/**
* 对日期的【月】进行加/减
*
* @param date 日期
* @param months 月数,负数为减
* @return 加/减几月后的日期
*/
public static Date addDateMonths(Date date, int months) {
DateTime dateTime = new DateTime(date);
return dateTime.plusMonths(months).toDate();
}
/**
* 对日期的【年】进行加/减
*
* @param date 日期
* @param years 年数,负数为减
* @return 加/减几年后的日期
*/
public static Date addDateYears(Date date, int years) {
DateTime dateTime = new DateTime(date);
return dateTime.plusYears(years).toDate();
}
}
四、加密
加密工具类用于对数据进行加密,这里是使用HmacSHA256加密算法进行加密,具体代码如下:
4.1 代码
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class HMACSHA256 {
public static String HMACSHA256(String key, String data) {
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
return byte2hex(mac.doFinal(data.getBytes()));
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
}
return null;
}
public static String byte2hex(byte[] b) {
StringBuilder hs = new StringBuilder();
String stmp;
for (int n = 0; b != null && n < b.length; n++) {
stmp = Integer.toHexString(b[n] & 0XFF);
if (stmp.length() == 1) {
hs.append('0');
}
hs.append(stmp);
}
return hs.toString().toUpperCase();
}
}
五、Http请求
Http请求工具类用于从request获取相关请求参数,如获取参数列表(ParameterMap)或者请求的Language参数.具体代码如下:
5.1 依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
5.2 代码
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* Http
*/
public class HttpContextUtils {
/**
* 获取http请求
* @return request
*/
public static HttpServletRequest getHttpServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return null;
}
return ((ServletRequestAttributes) requestAttributes).getRequest();
}
/**
* 获取http请求的请求参数列表
* @param request http请求
* @return 请求参数列表
*/
public static Map<String, String> getParameterMap(HttpServletRequest request) {
Enumeration<String> parameters = request.getParameterNames();
Map<String, String> params = new HashMap<>();
while (parameters.hasMoreElements()) {
String parameter = parameters.nextElement();
String value = request.getParameter(parameter);
if (StringUtils.isNotBlank(value)) {
params.put(parameter, value);
}
}
return params;
}
/**
* 获取域名 Domain
* @return Domain
*/
public static String getDomain() {
HttpServletRequest request = getHttpServletRequest();
StringBuffer url = request.getRequestURL();
return url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();
}
/**
* 获取请求地址
* @return origin
*/
public static String getOrigin() {
HttpServletRequest request = getHttpServletRequest();
return request.getHeader(HttpHeaders.ORIGIN);
}
/**
* 获取语言,默认返回 "zh-CN"
* @return language
*/
public static String getLanguage() {
// 默认语言
String defaultLanguage = "zh-CN";
// request
HttpServletRequest request = getHttpServletRequest();
if (request == null) {
return defaultLanguage;
}
// 请求语言
defaultLanguage = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
return defaultLanguage;
}
/**
* 获取请求消息头中的数据
*/
public static String getRequestReader(HttpServletRequest request) {
String line;
StringBuilder sb = new StringBuilder();
try {
while ((line = request.getReader().readLine()) != null) {
sb.append(line);
}
request.getReader().close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
}
六、金额
金额用于对金额数据进行转换,即带有¥格式的字符串数据,将其转换为方便存储和计算的数据,本工具类中将元转换为分.具体代码如下:
6.1代码
/**
* @author seaua
*/
public class MoneyUtil {
/**
* 获取金额,转换单位,元转换成分
*/
public static String getMoney(String amount) {
if (amount == null) {
return "0";
}
String currency = amount.replaceAll("[$¥,]", ""); // 处理包含, ¥
// 或者$的金额
int index = currency.indexOf(".");
int length = currency.length();
long amLong;
if (index == -1) {
amLong = Long.parseLong(currency + "00");
} else if (length - index >= 3) {
amLong = Long.parseLong((currency.substring(0, index + 3)).replace(".", ""));
} else if (length - index == 2) {
amLong = Long.parseLong((currency.substring(0, index + 2)).replace(".", "") + 0);
} else {
amLong = Long.parseLong((currency.substring(0, index + 1)).replace(".", "") + "00");
}
return Long.toString(amLong);
}
}
七、二维码
二维码工具类在实际开发中用于二维码的生成,在本工具类中createImageToLocal将生成的二维码存储到本地,createImage用于生成二维码并转换为base64字符串,用于在网络中传输.具体代码如下:
7.1 依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.70.ALL</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.3</version>
</dependency>
7.2 代码
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import com.alipay.api.internal.util.file.ByteArrayOutputStream;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import cn.hutool.core.codec.Base64Encoder;
public class QRCodeUtil {
// 二维码尺寸
public static final int QRCODE_SIZE = 300;
// 存放二维码的路径
public static final String PAY_PATH = "c://pay";
/**
* 生成二维码存到本地
*
* @param content 源内容
* @param outputStream 输出流
* @throws Exception
*/
public static void createImageToLocal(String content, OutputStream outputStream) throws Exception {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
// 存到磁盘
ImageIO.write(image, "jpg", outputStream);
}
/**
* 生成二维码
*
* @param content 源内容
* @return
* @throws Exception
*/
public static String createImage(String content) throws Exception {
Hashtable hints = new Hashtable();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
// 创建储存图片二进制流的输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "jpg", baos);
// 转成Base64格式
byte[] b = baos.toByteArray();
Base64Encoder encoder = new Base64Encoder();
return encoder.encode(b);
}
}
八、坐标转换
坐标转换用于不同地理坐标数据之间的转换,这在地理应用开发中经常用到,在本篇文章中的代码中实现gps84ToXY(wgs84到大地2000),GCJ02ToWGS84:火星坐标系(GCJ02)转地球坐标系(WGS84)具体代码如下:
8.1 代码
public class RtkUtils {
/**
* 将WGS84经纬度转为大地2000坐标
*
* @param B 纬度
* @param L 经度
* @param degree //
* @return
*/
public static double[] gps84ToXY(double B, double L, double degree) {
double[] xy = {0, 0};
double a = 6378137;//椭球长半轴
double b = 6356752.3142451795;//椭球短半轴
double e = 0.081819190842621;//第一偏心率
double eC = 0.0820944379496957;//第二偏心率
double L0 = 0;//中央子午线经度
int n = 0;//带号
if (degree == 6) {
//6度
n = (int) (Math.round((L + degree / 2) / degree));
L0 = degree * n - degree / 2;
} else {
//3度
n = (int) Math.round(L / degree);
L0 = degree * n;
}
//开始计算
double radB = B * Math.PI / 180;//纬度(弧度)
double radL = L * Math.PI / 180;//经度(弧度)
double deltaL = (L - L0) * Math.PI / 180;//经度差(弧度)
double N = a * a / b / Math.sqrt(1 + eC * eC * Math.cos(radB) * Math.cos(radB));
double C1 = 1.0 + 3.0 / 4 * e * e + 45.0 / 64 * Math.pow(e, 4) + 175.0 / 256 * Math.pow(e, 6) + 11025.0 / 16384 * Math.pow(e, 8);
double C2 = 3.0 / 4 * e * e + 15.0 / 16 * Math.pow(e, 4) + 525.0 / 512 * Math.pow(e, 6) + 2205.0 / 2048 * Math.pow(e, 8);
double C3 = 15.0 / 64 * Math.pow(e, 4) + 105.0 / 256 * Math.pow(e, 6) + 2205.0 / 4096 * Math.pow(e, 8);
double C4 = 35.0 / 512 * Math.pow(e, 6) + 315.0 / 2048 * Math.pow(e, 8);
double C5 = 315.0 / 131072 * Math.pow(e, 8);
double t = Math.tan(radB);
double eta = eC * Math.cos(radB);
double X = a * (1 - e * e) * (C1 * radB - C2 * Math.sin(2 * radB) / 2 + C3 * Math.sin(4 * radB) / 4 - C4 * Math.sin(6 * radB) / 6 + C5 * Math.sin(8 * radB));
xy[0] = X + N * Math.sin(radB) * Math.cos(radB) * Math.pow(deltaL, 2) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (5 - t * t + 9 * eta * eta + 4 * Math.pow(eta, 4)) / 12 + Math.pow(deltaL * Math.cos(radB), 4) * (61 - 58 * t * t + Math.pow(t, 4)) / 360) / 2;
xy[1] = N * deltaL * Math.cos(radB) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (1 - t * t + eta * eta) / 6 + Math.pow(deltaL * Math.cos(radB), 4) * (5 - 18 * t * t + Math.pow(t, 4) - 14 * eta * eta - 58 * eta * eta * t * t) / 120) + 500000;// +n * 1000000;
return xy;
}
private static final double PI = 3.1415926535897932384626;
// 卫星椭球坐标投影到平面地图坐标系的投影因子。 地球长半径
private static final double EARTH_MAJOR_RADIUS = 6378245.0;
// 椭球的偏心率。
private static final double ECCENTRICITY_RATIO = 0.00669342162296594323;
/**
* 火星坐标系(GCJ02)转地球坐标系(WGS84)
*
* @param gcjLat 火星坐标纬度
* @param gcjLng 火星坐标经度
*/
public static Double[] GCJ02ToWGS84(Double gcjLng, Double gcjLat) {
double dlat = transformlat(gcjLng - 105.0, gcjLat - 35.0);
double dlng = transformlng(gcjLng - 105.0, gcjLat - 35.0);
double radlat = gcjLat / 180.0 * PI;
double magic = Math.sin(radlat);
magic = 1 - ECCENTRICITY_RATIO * magic * magic;
double sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((EARTH_MAJOR_RADIUS * (1 - ECCENTRICITY_RATIO)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (EARTH_MAJOR_RADIUS / sqrtmagic * Math.cos(radlat) * PI);
double mglat = gcjLat + dlat;
double mglng = gcjLng + dlng;
return new Double[]{gcjLng * 2 - mglng, gcjLat * 2 - mglat};
}
private static Double transformlat(double lng, double lat) {
double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
return ret;
}
private static Double transformlng(double lng, double lat) {
double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
return ret;
}
}
九、树结构
树结构工具类在实际开发中用于处理树状结构,如菜单、部门数据的展示等,具体代码如下:
9.1代码
9.1.1 节点
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 树节点,所有需要实现树节点的,都需要继承该类
* @author seaua
*/
public class TreeNode<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private Long id;
/**
* 上级ID
*/
private Long pid;
/**
* 子节点列表
*/
private List<T> children = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getPid() {
return pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public List<T> getChildren() {
return children;
}
public void setChildren(List<T> children) {
this.children = children;
}
}
9.1.2 工具类
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* 树形结构工具类,如:菜单、部门等
*/
public class TreeUtils {
/**
* 根据pid,构建树节点
*/
public static <T extends TreeNode> List<T> build(List<T> treeNodes, Long pid) {
//pid不能为空
AssertUtils.isNull(pid, "pid");
List<T> treeList = new ArrayList<>();
for(T treeNode : treeNodes) {
if (pid.equals(treeNode.getPid())) {
treeList.add(findChildren(treeNodes, treeNode));
}
}
return treeList;
}
/**
* 查找子节点
*/
private static <T extends TreeNode> T findChildren(List<T> treeNodes, T rootNode) {
for(T treeNode : treeNodes) {
if(rootNode.getId().equals(treeNode.getPid())) {
rootNode.getChildren().add(findChildren(treeNodes, treeNode));
}
}
return rootNode;
}
/**
* 构建树节点
*/
public static <T extends TreeNode> List<T> build(List<T> treeNodes) {
List<T> result = new ArrayList<>();
//list转map
Map<Long, T> nodeMap = new LinkedHashMap<>(treeNodes.size());
for(T treeNode : treeNodes){
nodeMap.put(treeNode.getId(), treeNode);
}
for(T node : nodeMap.values()) {
T parent = nodeMap.get(node.getPid());
if(parent != null && !(node.getId().equals(parent.getId()))){
parent.getChildren().add(node);
continue;
}
result.add(node);
}
return result;
}
}
十、结语
上述为本人在实际开发中经常用到的工具类,您可以直接使用这些工具类代码,当然也可以优化这些类并扩展自己的相关功能。
如果你对区块链感兴趣,可以看一下我的区块链专栏.
感谢关注和收藏!