目录
一、编写目的
二、映射工具类
2.1 依赖
2.2 代码
三、日期格式
3.1 依赖
3.2 代码
四、加密
4.1 代码
五、Http请求
5.1 依赖
5.2 代码
六、金额
6.1 代码
七、二维码
7.1 依赖
7.2 代码
八、坐标转换
8.1 代码
九、树结构
9.1 代码
9.1.1 节点
9.1.2 工具类
十、结语
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;
}
}
十、结语
上述为本人在实际开发中经常用到的工具类,您可以直接使用这些工具类代码,当然也可以优化这些类并扩展自己的相关功能。
如果你对区块链感兴趣,可以看一下我的区块链专栏.
感谢关注和收藏!