一、树状结构工具类
package com.jowell.common.tree;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.beans.BeanMap;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* 树状结构工具类
*
* @author zhongjiawei
* @name TreeUtils
* @date 2022-09-23 11:05
*/
public class TreeUtils {
private TreeUtils() {
}
/**
* 默认的配置对象
*/
private static final TreeNodeConfig DEFAULT_CONFIG = createConfig(null, null, "sort"
, null, null);
/**
* 将源数据转化为树结构数据
*/
public static <T, E> List<Tree<E>> transform(List<T> treeDemoList, E rootId, TreeNodeConfig config) {
if (CollectionUtils.isNotEmpty(treeDemoList)) {
//#转树,Tree<>里面泛型为id的类型
return TreeUtil.build(treeDemoList, rootId, config, (object, tree) -> {
Map<String, T> map = BeanMap.create(object);
for (Map.Entry<String, T> entry : map.entrySet()) {
tree.putExtra(entry.getKey(), entry.getValue());
}
});
}
return Lists.newArrayList();
}
/**
* 将源数据转化为树结构数据
*
* @param treeDemoList 数据集
* @param rootId 根节点id
*/
public static <T, E> List<Tree<E>> transform(List<T> treeDemoList, E rootId) {
return transform(treeDemoList, rootId, DEFAULT_CONFIG);
}
/**
* 子节点查找父节点集(包含节点本身)
*/
public static <T, K> List<T> childToParent(List<T> treeDemoList, T node, Function<? super T, ? extends K> idMapper
, Function<? super T, ? extends K> parentIdMapper) {
if (CollectionUtils.isNotEmpty(treeDemoList)) {
//通过set添加查找后的实体
final Set<T> nodeList = new HashSet<>();
//将源数据转化为map
Map<? extends K, T> allMap = treeDemoList.stream().collect(
Collectors.toMap(idMapper, Function.identity(), (v1, v2) -> v2)
);
findParent(nodeList, node, allMap, parentIdMapper);
return new ArrayList<>(nodeList);
}
return Lists.newArrayList();
}
/**
* 节点查找子节点
*/
public static <T, E> Tree<E> parentToChile(List<T> treeDemoList, E id, E rootId) {
return parentToChile(transform(treeDemoList, rootId), id);
}
/**
* 节点查找子节点
*/
public static <E> Tree<E> parentToChile(List<Tree<E>> build, E id) {
Tree<E> childNode = new Tree<>();
if (CollectionUtils.isNotEmpty(build)) {
for (Tree<E> node : build) {
childNode = TreeUtil.getNode(node, id);
if (Objects.nonNull(childNode)) {
break;
}
}
}
return childNode;
}
/**
* 递归查找父节点
*/
private static <T, K> void findParent(Set<T> nodeList, T current, Map<? extends K, T> allMap
, Function<? super T, ? extends K> parentIdMapper) {
if (Objects.nonNull(current)) {
nodeList.add(current);
}
if (Objects.nonNull(current)) {
findParent(nodeList, allMap.get(parentIdMapper.apply(current)), allMap, parentIdMapper);
}
}
/**
* 默认的树状构建配置
*
* @param idKey
* @param parentIdKey
* @param weighKey
* @param deep 解析的最大深度
* @return
*/
private static TreeNodeConfig createConfig(String idKey, String parentIdKey, String weighKey
, String childrenKey, Integer deep) {
//#配置
TreeNodeConfig config = new TreeNodeConfig();
if (StringUtils.isNotBlank(idKey)) {
config.setIdKey(idKey);
}
if (StringUtils.isNotBlank(parentIdKey)) {
config.setParentIdKey(parentIdKey);
}
if (StringUtils.isNotBlank(weighKey)) {
config.setWeightKey(weighKey);
}
if (StringUtils.isNotBlank(childrenKey)) {
config.setChildrenKey(childrenKey);
}
if (deep != null) {
config.setDeep(deep);
}
return config;
}
}
1、数据库设计,一般也就这样设计的
2、代码实例
3、测试结果
二、参数校验断言工具类
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.Assert;
import java.util.Collection;
public class PaAssert {
private PaAssert() {
}
/**
* 通用的数据断言
*/
public static void isTrue(boolean condition, String miss) {
Assert.isTrue(condition, miss);
}
/**
* 对象判空
*/
public static void notNull(Object obj, String paramName) {
Assert.notNull(obj, convertMessage(paramName));
}
/**
* 字符对象判空
*/
public static void notBlank(String obj, String paramName) {
Assert.isTrue(obj != null && !obj.equals(""), convertMessage(paramName));
}
/**
* 查无数据提示
*/
public static void notData(Object obj) {
Assert.notNull(obj, "查无数据");
}
/**
* 查无数据提示
*/
public static void notData(Object obj, String sourceName) {
Assert.notNull(obj, "查无[" + sourceName + "]数据");
}
/**
* 集合判空
*/
public static void isCeNotEmpty(Collection<?> cel, String paramName) {
Assert.isTrue(CollectionUtils.isNotEmpty(cel), convertMessage(paramName));
}
private static String convertMessage(String paramName) {
return "[" + paramName + "]参数缺失";
}
}
三、StringUtil工具类
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.geesun.common.constant.Constants;
import com.geesun.common.core.text.StrFormatter;
import com.geesun.common.exception.base.BaseException;
import org.springframework.util.AntPathMatcher;
import org.apache.commons.lang3.StringUtils
public class StringUtils extends StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue)
{
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空, 包含List,Set,Queue
*
* @param coll 要判断的Collection
* @return true:为空 false:非空
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空,包含List,Set,Queue
*
* @param coll 要判断的Collection
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
** @return true:为空 false:非空
*/
public static boolean isEmpty(Object[] objects)
{
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Object[] objects)
{
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true:为空 false:非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true:非空 false:空
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true:为空 false:非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* 判断一个字符串是否为空串,如为空报错提示,不为空返回传递的字符串
*
* @param str String
* @param msg 提示消息
* @return 结果
*/
public static String isBlank(String str,String msg)
{
if (isNull(str) || NULLSTR.equals(str.trim())){
throw new BaseException(msg);
} else {
return str;
}
}
/**
* 判断一个字符串是否为空串,如为返回传递的字符串
*
* @param str String
* @param messagse 传递字符串
* @return 结果
*/
public static String isEmpty(String str,String messagse)
{
if (isNull(str) || NULLSTR.equals(str.trim())){
return messagse;
} else {
return str;
}
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true:非空串 false:空串
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true:为空 false:非空
*/
public static boolean isNull(Object object)
{
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true:非空 false:空
*/
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型(Java基本型别的数组)
*
* @param object 对象
* @return true:是数组 false:不是数组
*/
public static boolean isArray(Object object)
{
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
}
if (start < 0)
{
start = str.length() + start;
}
if (start < 0)
{
start = 0;
}
if (start > str.length())
{
return NULLSTR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
}
if (end < 0)
{
end = str.length() + end;
}
if (start < 0)
{
start = str.length() + start;
}
if (end > str.length())
{
end = str.length();
}
if (start > end)
{
return NULLSTR;
}
if (start < 0)
{
start = 0;
}
if (end < 0)
{
end = 0;
}
return str.substring(start, end);
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板,被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
return template;
}
return StrFormatter.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static final Set<String> str2Set(String str, String sep)
{
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
{
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str))
{
return list;
}
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str))
{
return list;
}
String[] split = str.split(sep);
for (String string : split)
{
if (filterBlank && StringUtils.isBlank(string))
{
continue;
}
if (trim)
{
string = string.trim();
}
list.add(string);
}
return list;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
{
if (isEmpty(cs) || isEmpty(searchCharSequences))
{
return false;
}
for (CharSequence testStr : searchCharSequences)
{
if (containsIgnoreCase(cs, testStr))
{
return true;
}
}
return false;
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str)
{
if (str == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (i > 0)
{
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
}
else
{
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1))
{
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
{
sb.append(SEPARATOR);
}
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
{
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线,仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法 例如:user_name->userName
*/
public static String toCamelCase(String s)
{
if (s == null)
{
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == SEPARATOR)
{
upperCase = true;
}
else if (upperCase)
{
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
sb.append(c);
}
}
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
return (T) obj;
}
/**
* 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式,该字符串为指定长度。
*/
public static final String padl(final Number num, final int size)
{
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
*/
public static final String padl(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
}
四、校验正则表达式工具类
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
/**
* @Author: Mr.zhongjiawei
* @Date: 2023-06-06 11:10
* @Description: 正则表达式工具类
*/
public class RegexUtil {
private RegexUtil(){}
/**
* 手机号验证规则
*/
private static String REGEX_PHONE = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(17[013678])|(18[0,5-9]))\\d{8}$";
/**
* 整数验证规则
*/
private static String REGEX_NUMBER = "^[0-9]*[1-9][0-9]*$";
/**
* 邮箱验证规则
*/
private static String REGEX_EMAIL = "^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$\n";
/**
* 校验手机号格式是否正确
*
* @param phone 手机号
* @return true/false
*/
public static boolean regexPhone(String phone) {
if ((phone != null) && (!phone.isEmpty())) {
return Pattern.matches(REGEX_PHONE, phone);
}
return false;
}
/**
* 校验数据是否是整数
* @param number 数据
* @return true/false
*/
public static boolean regexNumber(String number) {
if ((number != null) && (!number.isEmpty())) {
return Pattern.matches(REGEX_NUMBER, number);
}
return false;
}
/**
* 校验邮箱格式
*
* @param email 邮箱
* @return true/false
*/
public static boolean isValidEmail(String email) {
if ((email != null) && (!email.isEmpty())) {
return Pattern.matches(REGEX_EMAIL, email);
}
return false;
}
/**
* 校验身份证有效性
*
* @param idCard 身份证
* @return true/false
*/
public static boolean idCardVerify(String idCard) {
// 仅适用于18位标准身份证号码
if (idCard.length() != 18) {
return false;
}
// 使身份证号码中的字母升大写
idCard = idCard.toUpperCase();
char[] idCardChars = idCard.toCharArray();
//加权因子计算
final int[] factors = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
int sumFactor = 0;
for (int i = 0; i < factors.length; i++) {
// 数字的ASCII码是48-57
int value = idCardChars[i] - 48;
// 纯数字校验
if (value < 0 || value > 9) {
return false;
}
sumFactor += factors[i] * value;
}
// 校验码比对
final char[] verifyCode = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};
return idCardChars[17] == verifyCode[sumFactor % 11];
}
/**
* 判断字符串是否为日期格式(合法)
*
* @param inDate:字符串时间
* @return true/false
*/
public static boolean isValidDate(String inDate) {
if (inDate == null) {
return false;
}
// 或yyyy-MM-dd
SimpleDateFormat dataFormat = new SimpleDateFormat("yyyyMMdd");
if (inDate.trim().length() != dataFormat.toPattern().length()) {
return false;
}
// 该方法用于设置Calendar严格解析字符串;默认为true,宽松解析
dataFormat.setLenient(false);
try {
dataFormat.parse(inDate.trim());
} catch (ParseException e) {
return false;
}
return true;
}
}
五、Stream流工具类
/**
* Stream操作相关工具类
*
* @author wanfa
*/
public class StreamUtils {
private StreamUtils() {
}
/**
* 提取对象中的某一个属性
*
* @param srcList 对象list
* @param mapper 对象::get属性名
* @param <T> 对象类型
* @param <R> 属性类型
* @return 属性list
*/
public static <T, R> List<R> toList(List<T> srcList, Function<? super T, ? extends R> mapper) {
if (CollectionUtils.isEmpty(srcList)) {
return Lists.newArrayList();
}
return srcList.stream().map(mapper).collect(Collectors.toList());
}
/**
* 提取对象中的某一个属性,去重
*
* @param srcList 对象list
* @param mapper 对象::get属性名
* @param <T> 对象类型
* @param <R> 属性类型
* @return 属性set
*/
public static <T, R> Set<R> toSet(List<T> srcList, Function<? super T, ? extends R> mapper) {
if (CollectionUtils.isEmpty(srcList)) {
return Sets.newHashSet();
}
return srcList.stream().filter(e -> mapper.apply(e) != null).map(mapper).collect(Collectors.toSet());
}
/**
* ListSum求和
*
* @param srcList
* @param toIntFunction
* @param <T>
* @return
*/
public static <T> int sum(List<T> srcList, ToIntFunction<? super T> toIntFunction) {
if (CollectionUtils.isEmpty(srcList)) {
return 0;
}
return srcList.stream().mapToInt(toIntFunction).sum();
}
/**
* 构建 属性:属性 map
*
* @param srcList 对象list
* @param mapper1 对象::get属性名
* @param mapper2 对象::get属性名
* @param <T> 对象类型
* @param <K> 属性类型
* @param <U> 属性类型
* @return 属性:属性 map
*/
public static <T, K, U> Map<K, U> toMap(List<T> srcList,
Function<? super T, ? extends K> mapper1,
Function<? super T, ? extends U> mapper2) {
if (CollectionUtils.isEmpty(srcList)) {
return new HashMap<>();
}
return srcList.stream().collect(Collectors.toMap(mapper1, mapper2));
}
/**
* 构建 属性:属性 map
*
* @param srcList 对象list
* @param mapper1 对象::get属性名
* @param mapper2 对象::get属性名
* @param <T> 对象类型
* @param <K> 属性类型
* @param <U> 属性类型
* @return 属性:属性 map
*/
public static <T, K, U> Map<K, U> toMap(List<T> srcList,
Function<? super T, ? extends K> mapper1,
Function<? super T, ? extends U> mapper2,
BinaryOperator<U> mergeFunction) {
if (CollectionUtils.isEmpty(srcList)) {
return new HashMap<>();
}
return srcList.stream().collect(Collectors.toMap(mapper1, mapper2, mergeFunction));
}
/**
* 按特定规则筛选集合元素,返回List,过滤输入集合的null对象
*
* @param <T> 对象类型
* @param source 对象集合
* @param predicate 筛选条件
* @return
*/
public static <T> List<T> filter(Collection<T> source, Predicate<T> predicate) {
if (CollectionUtils.isEmpty(source)) {
return new ArrayList<>(0);
}
return source.stream().filter(Objects::nonNull).filter(predicate).collect(Collectors.toList());
}
/**
* 按匹配条件返回某一个对象,过滤输入集合的null对象
*
* @param <T> 对象类型
* @param source 对象集合
* @param predicate 匹配条件
* @return
*/
public static <T> T findAny(Collection<T> source, Predicate<T> predicate) {
if (CollectionUtils.isEmpty(source)) {
return null;
}
return source.stream().filter(Objects::nonNull).filter(predicate).findAny().orElse(null);
}
/**
* 判断集合是否有元素符合匹配条件
*
* @param <T> 对象类型
* @param source 对象集合
* @param predicate 匹配条件
* @return
*/
public static <T> boolean anyMatch(Collection<T> source, Predicate<T> predicate) {
if (CollectionUtils.isEmpty(source)) {
return false;
}
return source.stream().anyMatch(predicate);
}
/**
* list分组
*
* @param srcList 对象list
* @param keyMapper 分组属性
* @param <T>
* @param <R>
* @return
*/
public static <T, R> Map<R, List<T>> groupBy(List<T> srcList, Function<? super T, ? extends R> keyMapper) {
if (CollectionUtils.isEmpty(srcList)) {
return new HashMap<>();
}
return srcList.stream().collect(Collectors.groupingBy(keyMapper));
}
/**
* 获取最大值
*
* @param srcList 对象list
* @param keyMapper 对象获取方法
* @param <T>
* @return
*/
public static <T, V> V max(List<T> srcList, Function<? super T, ? extends Comparable<V>> keyMapper) {
if (CollUtil.isEmpty(srcList)) {
return null;
}
V result = null;
for (T t : srcList) {
if (keyMapper.apply(t) != null && (result == null || keyMapper.apply(t).compareTo(result) > 0)) {
result = (V) keyMapper.apply(t);
}
}
return result;
}
/**
* 获取最小值
*
* @param srcList 对象list
* @param keyMapper 对象获取方法
* @param <T>
* @return
*/
public static <T, V> V min(List<T> srcList, Function<? super T, ? extends Comparable<V>> keyMapper) {
if (CollUtil.isEmpty(srcList)) {
return null;
}
V result = null;
for (T t : srcList) {
if (keyMapper.apply(t) != null && (result == null || keyMapper.apply(t).compareTo(result) < 0)) {
result = (V) keyMapper.apply(t);
}
}
return result;
}
/**
* 所有的都要匹配
*
* @param collection 集合
* @param predicate 过滤条件
* @return boolean
*/
public static <T> boolean allMatch(Collection<T> collection, Predicate<T> predicate) {
if (CollUtil.isEmpty(collection)) {
return false;
}
return collection.stream().allMatch(predicate);
}
/**
* 根据某个属性去重
*/
public static <T> List<T> distinct(Collection<T> source, Function<? super T, ?> keyExtractor) {
if (CollectionUtils.isEmpty(source)) {
return new ArrayList<>(0);
}
return source.stream().filter(distinctByKey(keyExtractor))
.collect(Collectors.toList());
}
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Set<Object> seen = ConcurrentHashMap.newKeySet();
return t -> seen.add(keyExtractor.apply(t));
}
}