001/* 002 * Copyright 2024-2025, Warm-Flow (290631660@qq.com). 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.dromara.warm.flow.core.utils; 017 018import java.util.*; 019 020/** 021 * 字符串工具类 022 * 023 * @author warm 024 */ 025public class StringUtils { 026 /** 027 * 空字符串 028 */ 029 private static final String NULLSTR = ""; 030 031 /** 032 * 下划线 033 */ 034 private static final char SEPARATOR = '_'; 035 036 /** 037 * 获取参数不为空值 038 * 039 * @param value defaultValue 要判断的value 040 * @return value 返回值 041 */ 042 public static <T> T nvl(T value, T defaultValue) { 043 return value != null ? value : defaultValue; 044 } 045 046 /** 047 * * 判断一个字符串是否为空串 048 * 049 * @param str String 050 * @return true:为空 false:非空 051 */ 052 public static boolean isEmpty(String str) { 053 return ObjectUtil.isNull(str) || NULLSTR.equals(str.trim()); 054 } 055 056 /** 057 * * 判断一个字符串是否为非空串 058 * 059 * @param str String 060 * @return true:非空串 false:空串 061 */ 062 public static boolean isNotEmpty(String str) { 063 return !isEmpty(str); 064 } 065 066 /** 067 * 如果字符串是空,则返回默认值 068 * 069 * @param str 字符串 070 * @param defaultStr 默认值 071 * @return 结果 072 */ 073 public static String emptyDefault(String str, String defaultStr) { 074 return isEmpty(str) ? defaultStr : str; 075 } 076 077 /** 078 * 指定字符串数组中,是否包含空字符串 079 * 080 * @param strs 081 * @return 082 */ 083 public static boolean hasEmpty(String... strs) { 084 if (ArrayUtil.isEmpty(strs)) { 085 return true; 086 } 087 088 for (String str : strs) { 089 if (isEmpty(str)) { 090 return true; 091 } 092 } 093 return false; 094 } 095 096 /** 097 * 是否存都不为null或空对象或空白符的对象 098 * 099 * @param args 100 * @return 101 */ 102 public static boolean isAllNotEmpty(String... args) { 103 return false == hasEmpty(args); 104 } 105 106 /** 107 * 去空格 108 */ 109 public static String trim(String str) { 110 return (str == null ? "" : str.trim()); 111 } 112 113 /** 114 * 判断给定的collection列表中是否包含数组array 判断给定的数组array中是否包含给定的元素value 115 * 116 * @param collection 给定的集合 117 * @param array 给定的数组 118 * @return boolean 结果 119 */ 120 public static boolean containsAny(Collection<String> collection, String... array) { 121 if (CollUtil.isEmpty(collection) || ArrayUtil.isEmpty(array)) { 122 return false; 123 } else { 124 for (String str : array) { 125 if (collection.contains(str)) { 126 return true; 127 } 128 } 129 return false; 130 } 131 } 132 133 /** 134 * 截取字符串 135 * 136 * @param str 字符串 137 * @param start 开始 138 * @return 结果 139 */ 140 public static String substring(final String str, int start) { 141 if (str == null) { 142 return NULLSTR; 143 } 144 145 if (start < 0) { 146 start = str.length() + start; 147 } 148 149 if (start < 0) { 150 start = 0; 151 } 152 if (start > str.length()) { 153 return NULLSTR; 154 } 155 156 return str.substring(start); 157 } 158 159 /** 160 * 截取字符串 161 * 162 * @param str 字符串 163 * @param start 开始 164 * @param end 结束 165 * @return 结果 166 */ 167 public static String substring(final String str, int start, int end) { 168 if (str == null) { 169 return NULLSTR; 170 } 171 172 if (end < 0) { 173 end = str.length() + end; 174 } 175 if (start < 0) { 176 start = str.length() + start; 177 } 178 179 if (end > str.length()) { 180 end = str.length(); 181 } 182 183 if (start > end) { 184 return NULLSTR; 185 } 186 187 if (start < 0) { 188 start = 0; 189 } 190 if (end < 0) { 191 end = 0; 192 } 193 194 return str.substring(start, end); 195 } 196 197 /** 198 * 字符串转set 199 * 200 * @param str 字符串 201 * @param sep 分隔符 202 * @return set集合 203 */ 204 public static Set<String> str2Set(String str, String sep) { 205 return new HashSet<>(str2List(str, sep, true, false)); 206 } 207 208 /** 209 * 字符串转list 210 * 211 * @param str 字符串 212 * @param sep 分隔符 213 * @return list集合 214 */ 215 public static List<String> str2List(String str, String sep) { 216 return str2List(str, sep, true, true); 217 } 218 219 /** 220 * 字符串转list 221 * 222 * @param str 字符串 223 * @param sep 分隔符 224 * @param filterBlank 过滤纯空白 225 * @param trim 去掉首尾空白 226 * @return list集合 227 */ 228 public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) { 229 List<String> list = new ArrayList<String>(); 230 if (isEmpty(str)) { 231 return list; 232 } 233 234 // 过滤空白字符串 235 if (filterBlank && isEmpty(str)) { 236 return list; 237 } 238 String[] split = str.split(sep); 239 for (String string : split) { 240 if (filterBlank && isEmpty(string)) { 241 continue; 242 } 243 if (trim) { 244 string = string.trim(); 245 } 246 list.add(string); 247 } 248 249 return list; 250 } 251 252 /** 253 * 驼峰转下划线命名 254 */ 255 public static String toUnderScoreCase(String str) { 256 if (str == null) { 257 return null; 258 } 259 StringBuilder sb = new StringBuilder(); 260 // 前置字符是否大写 261 boolean preCharIsUpperCase = true; 262 // 当前字符是否大写 263 boolean curreCharIsUpperCase = true; 264 // 下一字符是否大写 265 boolean nexteCharIsUpperCase = true; 266 for (int i = 0; i < str.length(); i++) { 267 char c = str.charAt(i); 268 if (i > 0) { 269 preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); 270 } else { 271 preCharIsUpperCase = false; 272 } 273 274 curreCharIsUpperCase = Character.isUpperCase(c); 275 276 if (i < (str.length() - 1)) { 277 nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); 278 } 279 280 if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) { 281 sb.append(SEPARATOR); 282 } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) { 283 sb.append(SEPARATOR); 284 } 285 sb.append(Character.toLowerCase(c)); 286 } 287 288 return sb.toString(); 289 } 290 291 /** 292 * 是否包含字符串 293 * 294 * @param str 验证字符串 295 * @param strs 字符串组 296 * @return 包含返回true 297 */ 298 public static boolean inStringIgnoreCase(String str, String... strs) { 299 if (str != null && strs != null) { 300 for (String s : strs) { 301 if (str.equalsIgnoreCase(trim(s))) { 302 return true; 303 } 304 } 305 } 306 return false; 307 } 308 309 /** 310 * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld 311 * 312 * @param name 转换前的下划线大写方式命名的字符串 313 * @return 转换后的驼峰式命名的字符串 314 */ 315 public static String convertToCamelCase(String name) { 316 StringBuilder result = new StringBuilder(); 317 // 快速检查 318 if (name == null || name.isEmpty()) { 319 // 没必要转换 320 return ""; 321 } else if (!name.contains("_")) { 322 // 不含下划线,仅将首字母大写 323 return name.substring(0, 1).toUpperCase() + name.substring(1); 324 } 325 // 用下划线将原始字符串分割 326 String[] camels = name.split("_"); 327 for (String camel : camels) { 328 // 跳过原始字符串中开头、结尾的下换线或双重下划线 329 if (camel.isEmpty()) { 330 continue; 331 } 332 // 首字母大写 333 result.append(camel.substring(0, 1).toUpperCase()); 334 result.append(camel.substring(1).toLowerCase()); 335 } 336 return result.toString(); 337 } 338 339 /** 340 * 驼峰式命名法 341 * 例如:user_name->userName 342 */ 343 public static String toCamelCase(String s) { 344 if (s == null) { 345 return null; 346 } 347 if (s.indexOf(SEPARATOR) == -1) { 348 return s; 349 } 350 s = s.toLowerCase(); 351 StringBuilder sb = new StringBuilder(s.length()); 352 boolean upperCase = false; 353 for (int i = 0; i < s.length(); i++) { 354 char c = s.charAt(i); 355 356 if (c == SEPARATOR) { 357 upperCase = true; 358 } else if (upperCase) { 359 sb.append(Character.toUpperCase(c)); 360 upperCase = false; 361 } else { 362 sb.append(c); 363 } 364 } 365 return sb.toString(); 366 } 367 368 /** 369 * 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。 370 * 371 * @param num 数字对象 372 * @param size 字符串指定长度 373 * @return 返回数字的字符串格式,该字符串为指定长度。 374 */ 375 public static final String padl(final Number num, final int size) { 376 return padl(num.toString(), size, '0'); 377 } 378 379 /** 380 * 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。 381 * 382 * @param s 原始字符串 383 * @param size 字符串指定长度 384 * @param c 用于补齐的字符 385 * @return 返回指定长度的字符串,由原字符串左补齐或截取得到。 386 */ 387 public static final String padl(final String s, final int size, final char c) { 388 final StringBuilder sb = new StringBuilder(size); 389 if (s != null) { 390 final int len = s.length(); 391 if (s.length() <= size) { 392 for (int i = size - len; i > 0; i--) { 393 sb.append(c); 394 } 395 sb.append(s); 396 } else { 397 return s.substring(len - size, len); 398 } 399 } else { 400 for (int i = size; i > 0; i--) { 401 sb.append(c); 402 } 403 } 404 return sb.toString(); 405 } 406}