001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 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 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 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 com.mybatisflex.core.util; 017 018 019import java.util.Collection; 020import java.util.function.Function; 021import java.util.regex.Pattern; 022 023public class StringUtil { 024 025 private StringUtil() { 026 } 027 028 029 /** 030 * 第一个字符转换为小写 031 * 032 * @param string 033 */ 034 public static String firstCharToLowerCase(String string) { 035 char firstChar = string.charAt(0); 036 if (firstChar >= 'A' && firstChar <= 'Z') { 037 char[] chars = string.toCharArray(); 038 chars[0] += ('a' - 'A'); 039 return new String(chars); 040 } 041 return string; 042 } 043 044 045 /** 046 * 第一个字符转换为大写 047 * 048 * @param string 049 */ 050 public static String firstCharToUpperCase(String string) { 051 char firstChar = string.charAt(0); 052 if (firstChar >= 'a' && firstChar <= 'z') { 053 char[] chars = string.toCharArray(); 054 chars[0] -= ('a' - 'A'); 055 return new String(chars); 056 } 057 return string; 058 } 059 060 061 /** 062 * 驼峰转下划线格式 063 * 064 * @param string 065 */ 066 public static String camelToUnderline(String string) { 067 if (isBlank(string)) { 068 return ""; 069 } 070 int strLen = string.length(); 071 StringBuilder sb = new StringBuilder(strLen); 072 for (int i = 0; i < strLen; i++) { 073 char c = string.charAt(i); 074 if (Character.isUpperCase(c) && i > 0) { 075 sb.append('_'); 076 } 077 sb.append(Character.toLowerCase(c)); 078 } 079 return sb.toString(); 080 } 081 082 /** 083 * 下划线转驼峰格式 084 * 085 * @param string 086 */ 087 public static String underlineToCamel(String string) { 088 if (isBlank(string)) { 089 return ""; 090 } 091 if (Character.isUpperCase(string.charAt(0))) { 092 string = string.toLowerCase(); 093 } 094 int strLen = string.length(); 095 StringBuilder sb = new StringBuilder(strLen); 096 for (int i = 0; i < strLen; i++) { 097 char c = string.charAt(i); 098 if (c == '_') { 099 if (++i < strLen) { 100 sb.append(Character.toUpperCase(string.charAt(i))); 101 } 102 } else { 103 sb.append(c); 104 } 105 } 106 return sb.toString(); 107 } 108 109 110 /** 111 * 删除字符串中的字符 112 */ 113 public static String deleteChar(String string, char deleteChar) { 114 if (isBlank(string)) { 115 return ""; 116 } 117 char[] chars = string.toCharArray(); 118 StringBuilder sb = new StringBuilder(string.length()); 119 for (char aChar : chars) { 120 if (aChar != deleteChar) { 121 sb.append(aChar); 122 } 123 } 124 return sb.toString(); 125 } 126 127 /** 128 * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true 129 */ 130 public static boolean isBlank(String string) { 131 if (string == null) { 132 return true; 133 } 134 135 for (int i = 0, len = string.length(); i < len; i++) { 136 if (string.charAt(i) > ' ') { 137 return false; 138 } 139 } 140 return true; 141 } 142 143 144 public static boolean isAnyBlank(String... strings) { 145 if (strings == null || strings.length == 0) { 146 throw new IllegalArgumentException("strings is null or empty."); 147 } 148 149 for (String string : strings) { 150 if (isBlank(string)) { 151 return true; 152 } 153 } 154 return false; 155 } 156 157 158 public static boolean isNotBlank(String str) { 159 return !isBlank(str); 160 } 161 162 163 public static boolean areNotBlank(String... strings) { 164 return !isAnyBlank(); 165 } 166 167 168 /** 169 * 这个字符串是否是全是数字 170 * 171 * @param string 172 * @return 全部数数值时返回 true,否则返回 false 173 */ 174 public static boolean isNumeric(String string) { 175 if (isBlank(string)) { 176 return false; 177 } 178 for (int i = string.length(); --i >= 0; ) { 179 int chr = string.charAt(i); 180 if (chr < 48 || chr > 57) { 181 return false; 182 } 183 } 184 return true; 185 } 186 187 188 public static boolean startsWithAny(String string, String... prefixes) { 189 if (isBlank(string) || prefixes == null) { 190 return false; 191 } 192 193 for (String prefix : prefixes) { 194 if (string.startsWith(prefix)) { 195 return true; 196 } 197 } 198 return false; 199 } 200 201 202 public static boolean endsWithAny(String str, String... suffixes) { 203 if (isBlank(str) || suffixes == null) { 204 return false; 205 } 206 207 for (String suffix : suffixes) { 208 if (str.endsWith(suffix)) { 209 return true; 210 } 211 } 212 return false; 213 } 214 215 216 /** 217 * 正则匹配 218 * 219 * @param regex 220 * @param input 221 * @return 222 */ 223 public static boolean matches(String regex, String input) { 224 if (null == regex || null == input) { 225 return false; 226 } 227 return Pattern.matches(regex, input); 228 } 229 230 /** 231 * 合并字符串,优化 String.join() 方法 232 * 233 * @param delimiter 234 * @param elements 235 * @return 新拼接好的字符串 236 * @see String#join(CharSequence, CharSequence...) 237 */ 238 public static String join(String delimiter, CharSequence... elements) { 239 if (ArrayUtil.isEmpty(elements)) { 240 return ""; 241 } else if (elements.length == 1) { 242 return String.valueOf(elements[0]); 243 } else { 244 return String.join(delimiter, elements); 245 } 246 } 247 248 /** 249 * 合并字符串,优化 String.join() 方法 250 * 251 * @param delimiter 252 * @param elements 253 * @return 新拼接好的字符串 254 * @see String#join(CharSequence, CharSequence...) 255 */ 256 public static String join(String delimiter, Collection<? extends CharSequence> elements) { 257 if (CollectionUtil.isEmpty(elements)) { 258 return ""; 259 } else if (elements.size() == 1) { 260 return String.valueOf(elements.iterator().next()); 261 } else { 262 return String.join(delimiter, elements); 263 } 264 } 265 266 267 /** 268 * 合并字符串,优化 String.join() 方法 269 * 270 * @param delimiter 271 * @param objs 272 * @param function 273 * @param <T> 274 */ 275 public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) { 276 if (CollectionUtil.isEmpty(objs)) { 277 return ""; 278 } else if (objs.size() == 1) { 279 T next = objs.iterator().next(); 280 return String.valueOf(function.apply(next)); 281 } else { 282 String[] strings = new String[objs.size()]; 283 int index = 0; 284 for (T obj : objs) { 285 strings[index++] = function.apply(obj); 286 } 287 return String.join(delimiter, strings); 288 } 289 } 290 291 public static String buildSchemaWithTable(String schema, String tableName) { 292 return isNotBlank(schema) ? schema + "." + tableName : tableName; 293 } 294 295 public static String[] getSchemaAndTableName(String tableNameWithSchema) { 296 int index = tableNameWithSchema.indexOf("."); 297 return index <= 0 ? new String[]{null, tableNameWithSchema.trim()} 298 : new String[]{tableNameWithSchema.substring(0, index).trim(), tableNameWithSchema.substring(index + 1).trim()}; 299 } 300 301 public static String[] getTableNameWithAlias(String tableNameWithAlias) { 302 int index = tableNameWithAlias.indexOf("."); 303 return index <= 0 ? new String[]{tableNameWithAlias, null} 304 : new String[]{tableNameWithAlias.substring(0, index), tableNameWithAlias.substring(index + 1)}; 305 } 306 307 public static String tryTrim(String string) { 308 return string != null ? string.trim() : null; 309 } 310 311 public static String substringAfterLast(String text, String prefix) { 312 if (text == null) { 313 return null; 314 } 315 if (prefix == null) { 316 return text; 317 } 318 return text.substring(text.lastIndexOf(prefix) + 1); 319 } 320 321 322}