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
026    /**
027     * 第一个字符转换为小写
028     *
029     * @param string
030     */
031    public static String firstCharToLowerCase(String string) {
032        char firstChar = string.charAt(0);
033        if (firstChar >= 'A' && firstChar <= 'Z') {
034            char[] arr = string.toCharArray();
035            arr[0] += ('a' - 'A');
036            return new String(arr);
037        }
038        return string;
039    }
040
041
042    /**
043     * 第一个字符转换为大写
044     *
045     * @param string
046     */
047    public static String firstCharToUpperCase(String string) {
048        char firstChar = string.charAt(0);
049        if (firstChar >= 'a' && firstChar <= 'z') {
050            char[] arr = string.toCharArray();
051            arr[0] -= ('a' - 'A');
052            return new String(arr);
053        }
054        return string;
055    }
056
057
058    /**
059     * 驼峰转下划线格式
060     *
061     * @param string
062     */
063    public static String camelToUnderline(String string) {
064        if (isBlank(string)) {
065            return "";
066        }
067        int strLen = string.length();
068        StringBuilder sb = new StringBuilder(strLen);
069        for (int i = 0; i < strLen; i++) {
070            char c = string.charAt(i);
071            if (Character.isUpperCase(c) && i > 0) {
072                sb.append('_');
073            }
074            sb.append(Character.toLowerCase(c));
075        }
076        return sb.toString();
077    }
078
079    /**
080     * 下划线转驼峰格式
081     *
082     * @param string
083     */
084    public static String underlineToCamel(String string) {
085        if (isBlank(string)) {
086            return "";
087        }
088        String temp = string.toLowerCase();
089        int strLen = temp.length();
090        StringBuilder sb = new StringBuilder(strLen);
091        for (int i = 0; i < strLen; i++) {
092            char c = temp.charAt(i);
093            if (c == '_') {
094                if (++i < strLen) {
095                    sb.append(Character.toUpperCase(temp.charAt(i)));
096                }
097            } else {
098                sb.append(c);
099            }
100        }
101        return sb.toString();
102    }
103
104    /**
105     * 字符串为 null 或者内部字符全部为 ' ', '\t', '\n', '\r' 这四类字符时返回 true
106     */
107    public static boolean isBlank(String str) {
108        if (str == null) {
109            return true;
110        }
111
112        for (int i = 0, len = str.length(); i < len; i++) {
113            if (str.charAt(i) > ' ') {
114                return false;
115            }
116        }
117        return true;
118    }
119
120
121    public static boolean isAnyBlank(String... strings) {
122        if (strings == null || strings.length == 0) {
123            throw new IllegalArgumentException("args is empty.");
124        }
125
126        for (String str : strings) {
127            if (isBlank(str)) {
128                return true;
129            }
130        }
131        return false;
132    }
133
134
135    public static boolean isNotBlank(String str) {
136        return !isBlank(str);
137    }
138
139
140    public static boolean areNotBlank(String... strings) {
141        return !isAnyBlank();
142    }
143
144
145    /**
146     * 这个字符串是否是全是数字
147     *
148     * @param str
149     * @return
150     */
151    public static boolean isNumeric(String str) {
152        if (isBlank(str)) {
153            return false;
154        }
155        for (int i = str.length(); --i >= 0; ) {
156            int chr = str.charAt(i);
157            if (chr < 48 || chr > 57) {
158                return false;
159            }
160        }
161        return true;
162    }
163
164
165    public static boolean startsWithAny(String str, String... prefixes) {
166        if (isBlank(str) || prefixes == null || prefixes.length == 0) {
167            return false;
168        }
169
170        for (String prefix : prefixes) {
171            if (str.startsWith(prefix)) {
172                return true;
173            }
174        }
175        return false;
176    }
177
178
179    public static boolean endsWithAny(String str, String... suffixes) {
180        if (isBlank(str) || suffixes == null || suffixes.length == 0) {
181            return false;
182        }
183
184        for (String suffix : suffixes) {
185            if (str.endsWith(suffix)) {
186                return true;
187            }
188        }
189        return false;
190    }
191
192
193    public static String trimOrNull(String string) {
194        return string != null ? string.trim() : null;
195    }
196
197
198    /**
199     * 正则匹配
200     *
201     * @param regex
202     * @param input
203     * @return
204     */
205    public static boolean matches(String regex, String input) {
206        if (null == regex || null == input) {
207            return false;
208        }
209        return Pattern.matches(regex, input);
210    }
211
212    /**
213     * 合并字符串,优化 String.join() 方法
214     *
215     * @param delimiter
216     * @param elements
217     * @return 新拼接好的字符串
218     * @see String#join(CharSequence, CharSequence...)
219     */
220    public static String join(String delimiter, CharSequence... elements) {
221        if (ArrayUtil.isEmpty(elements)) {
222            return "";
223        } else if (elements.length == 1) {
224            return String.valueOf(elements[0]);
225        } else {
226            return String.join(delimiter, elements);
227        }
228    }
229
230
231    /**
232     * 合并字符串,优化 String.join() 方法
233     *
234     * @param delimiter
235     * @param elements
236     * @return 新拼接好的字符串
237     * @see String#join(CharSequence, CharSequence...)
238     */
239    public static String join(String delimiter, Collection<? extends CharSequence> elements) {
240        if (CollectionUtil.isEmpty(elements)) {
241            return "";
242        } else if (elements.size() == 1) {
243            return String.valueOf(elements.iterator().next());
244        } else {
245            return String.join(delimiter, elements);
246        }
247    }
248
249    /**
250     * 合并字符串,优化 String.join() 方法
251     *
252     * @param delimiter
253     * @param objs
254     * @param function
255     * @param <T>
256     * @return
257     */
258    public static <T> String join(String delimiter, Collection<T> objs, Function<T, String> function) {
259        if (CollectionUtil.isEmpty(objs)) {
260            return "";
261        } else if (objs.size() == 1) {
262            T next = objs.iterator().next();
263            return String.valueOf(function.apply(next));
264        } else {
265            String[] strings = new String[objs.size()];
266            int index = 0;
267            for (T obj : objs) {
268                strings[index++] = function.apply(obj);
269            }
270            return String.join(delimiter, strings);
271        }
272    }
273
274
275}