All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.iofairy.top.S Maven / Gradle / Ivy

/*
 * Copyright (C) 2021 iofairy, 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.iofairy.top;

import com.iofairy.except.UnexpectedParameterException;
import com.iofairy.tuple.Tuple;
import com.iofairy.tuple.Tuple2;

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

/**
 * Global Variables And Methods for {@link String} Operations. 
* 字符串相关操作的常用变量与函数。
* >>>>>>
* 采用简单类名 S (String) 模拟类似 Kotlin 的 Top-level function(顶级函数、全局函数) * * @since 0.3.0 */ public final class S { /** * Whether CharSequence array contains {@code null} or empty {@code ""} * or CharSequence array is {@code null}.
* Especially, when length of CharSequence array is 0 ({@code css.length == 0}), return {@code true}.
* 数组中包含{@code null}值或者空字符串{@code ""}或者CharSequence数组本身就为{@code null},则返回true。 * 特别地,当数组本身长度等于0时,也返回true。 * * @param css CharSequence array * @return {@code true} or {@code false} * @since 0.0.1 */ public static boolean hasEmpty(CharSequence... css) { if (css == null) return true; if (css.length == 0) return true; boolean hasEmpty = false; for (CharSequence cs : css) { if (isEmpty(cs)) { hasEmpty = true; break; } } return hasEmpty; } /** * {@code true} if all array values are {@code null} or empty {@code ""} value * or CharSequence array is {@code null}.
* Especially, when length of CharSequence array is 0 ({@code css.length == 0}), return {@code true}.
* 数组中所有的值都是{@code null}或者空字符串{@code ""}或者CharSequence数组本身就为{@code null},则返回{@code true}。 * 特别地,当数组本身长度等于0时,也返回true。 * * @param css CharSequence array * @return {@code true} or {@code false} * @since 0.0.1 */ public static boolean allEmpty(CharSequence... css) { if (css == null) return true; if (css.length == 0) return true; return Arrays.stream(css).allMatch(G::isEmpty); } /** * Whether CharSequence array contains {@code null} or empty {@code ""} or blank * or CharSequence array is {@code null}.
* Especially, when length of CharSequence array is 0 ({@code css.length == 0}), return {@code true}.
* 数组中包含{@code null}值或空字符串{@code ""}或空白字符串或CharSequence数组本身就为{@code null},则返回true。 * 特别地,当数组本身长度等于0时,也返回true。 * * @param css string array * @return {@code true} or {@code false} * @see #isBlank(CharSequence) * @since 0.0.1 */ public static boolean hasBlank(CharSequence... css) { if (css == null) return true; if (css.length == 0) return true; boolean hasBlank = false; for (CharSequence cs : css) { if (isBlank(cs)) { hasBlank = true; break; } } return hasBlank; } /** * {@code true} if all array values are {@code null} or empty {@code ""} or blank * or CharSequence array is {@code null}.
* Especially, when length of CharSequence array is 0 ({@code css.length == 0}), return {@code true}.
* 数组中所有的值都是{@code null}或空字符串{@code ""}或空白字符串或CharSequence数组本身就为{@code null},则返回{@code true}。 * 特别地,当数组本身长度等于0时,也返回true。 * * @param css CharSequence array * @return {@code true} or {@code false} * @see #isBlank(CharSequence) * @since 0.0.1 */ public static boolean allBlank(CharSequence... css) { if (css == null) return true; if (css.length == 0) return true; return Arrays.stream(css).allMatch(S::isBlank); } /** * Whether CharSequence List contains {@code null} or empty {@code ""} * or CharSequence List is {@code null}.
* Especially, when length of CharSequence List is 0 ({@code css.length == 0}), return {@code true}.
* 列表中包含{@code null}值或者空字符串{@code ""}或者CharSequence列表本身就为{@code null},则返回true。 * 特别地,当列表本身长度等于0时,也返回true。 * * @param css CharSequence List * @return {@code true} or {@code false} * @since 0.3.0 */ public static boolean hasEmpty(Collection css) { if (css == null) return true; if (css.isEmpty()) return true; boolean hasEmpty = false; for (CharSequence cs : css) { if (isEmpty(cs)) { hasEmpty = true; break; } } return hasEmpty; } /** * {@code true} if all List values are {@code null} or empty {@code ""} value * or CharSequence List is {@code null}.
* Especially, when length of CharSequence List is 0 ({@code css.length == 0}), return {@code true}.
* 列表中所有的值都是{@code null}或者空字符串{@code ""}或者CharSequence列表本身就为{@code null},则返回{@code true}。 * 特别地,当列表本身长度等于0时,也返回true。 * * @param css CharSequence List * @return {@code true} or {@code false} * @since 0.3.0 */ public static boolean allEmpty(Collection css) { if (css == null) return true; if (css.isEmpty()) return true; return css.stream().allMatch(G::isEmpty); } /** * Whether CharSequence List contains {@code null} or empty {@code ""} or blank * or CharSequence List is {@code null}.
* Especially, when length of CharSequence List is 0 ({@code css.length == 0}), return {@code true}.
* 列表中包含{@code null}值或空字符串{@code ""}或空白字符串或CharSequence列表本身就为{@code null},则返回true。 * 特别地,当列表本身长度等于0时,也返回true。 * * @param css string List * @return {@code true} or {@code false} * @see #isBlank(CharSequence) * @since 0.3.0 */ public static boolean hasBlank(Collection css) { if (css == null) return true; if (css.isEmpty()) return true; boolean hasBlank = false; for (CharSequence cs : css) { if (isBlank(cs)) { hasBlank = true; break; } } return hasBlank; } /** * {@code true} if all List values are {@code null} or empty {@code ""} or blank * or CharSequence List is {@code null}.
* Especially, when length of CharSequence List is 0 ({@code css.length == 0}), return {@code true}.
* 列表中所有的值都是{@code null}或空字符串{@code ""}或空白字符串或CharSequence列表本身就为{@code null},则返回{@code true}。 * 特别地,当列表本身长度等于0时,也返回true。 * * @param css CharSequence List * @return {@code true} or {@code false} * @see #isBlank(CharSequence) * @since 0.3.0 */ public static boolean allBlank(Collection css) { if (css == null) return true; if (css.isEmpty()) return true; return css.stream().allMatch(S::isBlank); } /** * {@code true} if all chars in CharSequence are whitespace {@link Character#isWhitespace(char)}.
* 字符序列中的所有字符都是空白字符,则返回true。 * * @param cs CharSequence * @return {@code true} or {@code false} * @since 0.0.1 */ public static boolean isBlank(CharSequence cs) { int strLen; if (cs != null && (strLen = cs.length()) != 0) { for (int i = 0; i < strLen; ++i) { if (!isBlankChar(cs.charAt(i))) return false; } } return true; } public static boolean isBlankChar(char c) { return isBlankChar((int) c); } public static boolean isBlankChar(int c) { return Character.isWhitespace(c) || Character.isSpaceChar(c); } public static boolean isEmpty(CharSequence cs) { return cs == null || cs.length() == 0; } /** * Returns itself if string is non-null; otherwise, returns empty({@code ""}). * * @param s string * @return itself or empty({@code ""}) */ public static String nullToEmpty(String s) { return isEmpty(s) ? "" : s; } /** * Returns itself if string is non-empty; otherwise, returns {@code null}. * * @param s string * @return itself or {@code null} */ public static String emptyToNull(String s) { return isEmpty(s) ? null : s; } /** * Returns itself if string is non-blank; otherwise, returns {@code null}. * * @param s string * @return itself or {@code null} */ public static String blankToNull(String s) { return isBlank(s) ? null : s; } /** * Returns itself if string is non-blank; otherwise, returns empty({@code ""}). * * @param s string * @return itself or empty({@code ""}). */ public static String blankToEmpty(String s) { return isBlank(s) ? "" : s; } /** * Padding chars to the left of the input char sequence to the given length.
* 在字符串左侧添加字符以达到给定的长度 * * @param cs input char sequence * @param padChar pad char * @param length final length of returns string * @return string * @since 0.3.7 */ public static String padLeftChars(CharSequence cs, char padChar, int length) { if (cs == null) return null; if (cs.length() >= length) return cs.toString(); int padLength = length - cs.length(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < padLength; i++) { sb.append(padChar); } sb.append(cs); return sb.toString(); } /** * Padding chars to the left of the input number to the given length.
* 在数字左侧添加字符以达到给定的长度 * * @param number input number * @param padChar pad char * @param length final length of returns string * @return string * @since 0.3.7 */ public static String padLeftChars(Number number, char padChar, int length) { if (number == null) return null; String numberStr = G.toString(number); return padLeftChars(numberStr, padChar, length); } /** * Padding chars to the right of the input char sequence to the given length.
* 在字符串右侧添加字符以达到给定的长度 * * @param cs input char sequence * @param padChar pad char * @param length final length of returns string * @return string * @since 0.4.15 */ public static String padRightChars(CharSequence cs, char padChar, int length) { if (cs == null) return null; if (cs.length() >= length) return cs.toString(); int padLength = length - cs.length(); StringBuilder sb = new StringBuilder(); sb.append(cs); for (int i = 0; i < padLength; i++) { sb.append(padChar); } return sb.toString(); } /** * Padding chars to the right of the input number to the given length.
* 在数字右侧添加字符以达到给定的长度 * * @param number input number * @param padChar pad char * @param length final length of returns string * @return string * @since 0.4.15 */ public static String padRightChars(Number number, char padChar, int length) { if (number == null) return null; String numberStr = G.toString(number); return padRightChars(numberStr, padChar, length); } /** * Tests if the given string ends with the specified suffix, when compared starting from the specified offset from the end of the string.
* 检查给定的字符串是否以指定的后缀结尾,从字符串末尾的指定偏移量开始比较。 * * @param str the string to check * @param suffix the suffix to check for * @param offsetFromEnd the offset from the end of the string to start the comparison from. 从字符串末尾开始的偏移量 * @return true if the given string ends with the specified suffix, false otherwise * @since 0.3.11 */ public static boolean endsWith(String str, String suffix, int offsetFromEnd) { if (str == null || suffix == null || offsetFromEnd < 0) return false; return str.startsWith(suffix, str.length() - offsetFromEnd - suffix.length()); } /** * Trims the string and returns a string that does not start with {@code trimHeadStr} and does not end with {@code trimTailStr}.
* 修剪字符串,并返回不以 {@code trimHeadStr} 开头 且 不以 {@code trimTailStr} 结尾的字符串 * * @param str 待修剪的字符串 * @param trimHeadStr 修剪头部指定的字符串 * @param trimTailStr 修剪尾部指定的字符串 * @return 修剪后的字符串 * @since 0.3.11 */ public static String trim(String str, String trimHeadStr, String trimTailStr) { return trim(str, trimHeadStr, trimTailStr, true); } /** * Trims the string and returns a string that does not start with {@code trimHeadStr} and does not end with {@code trimTailStr}.
* 修剪字符串,并返回不以 {@code trimHeadStr} 开头 且 不以 {@code trimTailStr} 结尾的字符串 * * @param str 待修剪的字符串 * @param trimHeadStr 修剪头部指定的字符串 * @param trimTailStr 修剪尾部指定的字符串 * @param isTrimHeadFirst true,先修剪头部,再修剪尾部;false,先修剪尾部,再修剪头部 * @return 修剪后的字符串 * @since 0.3.11 */ public static String trim(String str, String trimHeadStr, String trimTailStr, boolean isTrimHeadFirst) { if (isEmpty(str)) return str; int start = 0; int end = str.length(); if (isTrimHeadFirst) { if (!isEmpty(trimHeadStr)) { while (start < end && str.startsWith(trimHeadStr, start)) { start += trimHeadStr.length(); } } if (!isEmpty(trimTailStr)) { while (end - trimTailStr.length() >= start && endsWith(str, trimTailStr, str.length() - end)) { end -= trimTailStr.length(); } } } else { if (!isEmpty(trimTailStr)) { while (end - trimTailStr.length() >= start && endsWith(str, trimTailStr, str.length() - end)) { end -= trimTailStr.length(); } } if (!isEmpty(trimHeadStr)) { while (start < end && str.startsWith(trimHeadStr, start)) { start += trimHeadStr.length(); } } } return str.substring(start, end); } /** * Trim the given string once with the specified header string and tail string.
* 使用指定的头部字符串与尾部字符串对给定的字符串修剪一次 * * @param str 待修剪的字符串 * @param trimHeadStr 修剪头部指定的字符串 * @param trimTailStr 修剪尾部指定的字符串 * @return 修剪后的字符串 * @since 0.3.11 */ public static String trimOnce(String str, String trimHeadStr, String trimTailStr) { return trimOnce(str, trimHeadStr, trimTailStr, true); } /** * Trim the given string once with the specified header string and tail string.
* 使用指定的头部字符串与尾部字符串对给定的字符串修剪一次 * * @param str 待修剪的字符串 * @param trimHeadStr 修剪头部指定的字符串 * @param trimTailStr 修剪尾部指定的字符串 * @param isTrimHeadFirst true,先修剪头部,再修剪尾部;false,先修剪尾部,再修剪头部 * @return 修剪后的字符串 * @since 0.3.11 */ public static String trimOnce(String str, String trimHeadStr, String trimTailStr, boolean isTrimHeadFirst) { if (isEmpty(str)) return str; if (isTrimHeadFirst) { if (!isEmpty(trimHeadStr) && str.startsWith(trimHeadStr)) { str = str.substring(trimHeadStr.length()); } if (!isEmpty(trimTailStr) && str.endsWith(trimTailStr)) { str = str.substring(0, str.length() - trimTailStr.length()); } } else { if (!isEmpty(trimTailStr) && str.endsWith(trimTailStr)) { str = str.substring(0, str.length() - trimTailStr.length()); } if (!isEmpty(trimHeadStr) && str.startsWith(trimHeadStr)) { str = str.substring(trimHeadStr.length()); } } return str; } /** * Using string to enclose a String
*

Examples: *

{@code
     * S.enclose("abc", "||");              // returns "||abc||";
     * }
* * @param enclosedStr 被包围的字符串 * @param encloseStr 包围的字符串 * @return 包围后的字符串 * @since 0.3.11 */ public static String enclose(String enclosedStr, String encloseStr) { return enclose(enclosedStr, encloseStr, encloseStr); } /** * Using two strings to enclose a String
*

Examples: *

{@code
     * S.enclose("abc", ">>", "<<");            // returns ">>abc<<";
     * }
* * @param enclosedStr 被包围的字符串 * @param encloseStr1 包围的字符串1 * @param encloseStr2 包围的字符串2 * @return 包围后的字符串 * @since 0.3.11 */ public static String enclose(String enclosedStr, String encloseStr1, String encloseStr2) { if (enclosedStr == null) return null; if (encloseStr1 == null) encloseStr1 = ""; if (encloseStr2 == null) encloseStr2 = ""; return encloseStr1 + enclosedStr + encloseStr2; } /** * Using char to enclose a String *

Examples: *

{@code
     * S.enclose("abc", '"');                   // returns "\"abc\"";
     * }
* * @param enclosedStr 被包围的字符串 * @param encloseChar 包围的字符 * @return 包围后的字符串 * @since 0.3.11 */ public static String enclose(String enclosedStr, char encloseChar) { return enclose(enclosedStr, encloseChar, encloseChar); } /** * Using two chars to enclose a String *

Examples: *

{@code
     * S.enclose("abc", '>', '<');              // returns ">abc<";
     * }
* * @param enclosedStr 被包围的字符串 * @param encloseChar1 包围的字符1 * @param encloseChar2 包围的字符2 * @return 包围后的字符串 * @since 0.3.11 */ public static String enclose(String enclosedStr, char encloseChar1, char encloseChar2) { if (enclosedStr == null) return null; return encloseChar1 + enclosedStr + encloseChar2; } /** * Split by the place where the delimiter first appears, only split once.
* 在分隔符第一次出现的地方切分字符串,将一个字符串分隔成两个字符串 * * @param source will be split * @param delimiter delimiter * @return Tuple2<String, String> -- first substring and second substring * @since 0.2.0 */ public static Tuple2 splitOnce(String source, String delimiter) { if (hasEmpty(source, delimiter)) return Tuple.of(source, null); int index = source.indexOf(delimiter); if (index > -1) { return Tuple.of(source.substring(0, index), source.substring(index + delimiter.length())); } else { return Tuple.of(source, null); } } /** * The index within this string of the specified occurrence order of the specified substring.
* 获取指定的子字符串的指定出现次序在原字符串中的位置序号 * * @param source 原字符串 * @param subStr 要匹配的子字符串 * @param appearanceOrder 出现的次序(第几次出现),从 1 开始计数 * @return index * @throws NullPointerException if {@code source} or {@code subStr} is null * @throws UnexpectedParameterException if {@code appearanceOrder} less than 1. * @since 0.3.11 */ public static int indexOf(String source, String subStr, int appearanceOrder) { if (source == null || subStr == null) throw new NullPointerException("Parameters `source`, `subStr` must be non-null!"); if (appearanceOrder < 1) throw new UnexpectedParameterException("Parameter `appearanceOrder` must be greater than 0"); int index = -1; int count = 0; while ((index = source.indexOf(subStr, index + 1)) != -1) { count++; if (count == appearanceOrder) { return index; } } return -1; } /** * Counts how many times the char occurrences in the given string. * * @param str input string * @param c match character * @return the number of occurrences * @since 0.3.0 */ public static int countChars(final CharSequence str, final char c) { if (isEmpty(str)) return 0; int count = 0; for (int i = 0; i < str.length(); i++) { if (c == str.charAt(i)) { count++; } } return count; } /** * Counts how many times the char in char array occurrences in the given string. *

Examples: *

{@code
     * S.countMultiChars("abc- Defgh_IJ--klm  _nop-", '-', ' ', 'z', '_');    // returns [4, 3, 0, 2];
     *                                                                        // --------------------
     *                                                                        // The number of '-': 4
     *                                                                        // The number of ' ': 3
     *                                                                        // The number of 'z': 0
     *                                                                        // The number of '_': 2
     * }
* * @param str string * @param cs char array * @return each char occurrences times * @since 0.3.0 */ public static int[] countMultiChars(final CharSequence str, final char... cs) { if (G.isEmpty(cs)) return new int[0]; int length = cs.length; int[] counts = new int[length]; if (isEmpty(str)) return counts; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); for (int j = 0; j < cs.length; j++) { if (c == cs[j]) { counts[j] += 1; break; } } } return counts; } /** * Counts how many times the char in {@link CharSequence} occurrences in the given string. *

Examples: *

{@code
     * S.countMultiChars("abc- Defgh_IJ--klm  _nop-", "- z_");    // returns [4, 3, 0, 2];
     *                                                            // --------------------
     *                                                            // The number of '-': 4
     *                                                            // The number of ' ': 3
     *                                                            // The number of 'z': 0
     *                                                            // The number of '_': 2
     * }
* * @param str string * @param chars {@link CharSequence} * @return each char occurrences times * @since 0.3.0 */ public static int[] countMultiChars(final CharSequence str, final CharSequence chars) { if (G.isEmpty(chars)) return new int[0]; int length = chars.length(); int[] counts = new int[length]; if (isEmpty(str)) return counts; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); for (int j = 0; j < chars.length(); j++) { if (c == chars.charAt(j)) { counts[j] += 1; break; } } } return counts; } /** * Formats a given number according to a default pattern. * * @param number The number to be formatted. * @return The formatted number as a string. * @since 0.4.10 */ public static String format(Number number) { return format(number, "#.##", RoundingMode.HALF_UP, false); } /** * Formats a given number according to a specified pattern. * * @param number The number to be formatted. * @param pattern The pattern to be applied during formatting. * @return The formatted number as a string. * @since 0.4.9 */ public static String format(Number number, String pattern) { return format(number, pattern, RoundingMode.HALF_UP, false); } /** * Formats a given number according to a specified pattern with a specific rounding mode. * * @param number The number to be formatted. * @param pattern The pattern to be applied during formatting. * @param roundingMode The rounding mode to be used during formatting. * @return The formatted number as a string. * @since 0.4.9 */ public static String format(Number number, String pattern, RoundingMode roundingMode) { return format(number, pattern, roundingMode, false); } /** * Formats a given number according to a default pattern. * * @param number The number to be formatted. * @param isNullToZero Is {@code null} to {@code 0} * @return The formatted number as a string. * @since 0.4.10 */ public static String format(Number number, boolean isNullToZero) { return format(number, "#.##", RoundingMode.HALF_UP, isNullToZero); } /** * Formats a given number according to a specified pattern. * * @param number The number to be formatted. * @param pattern The pattern to be applied during formatting. * @param isNullToZero Is {@code null} to {@code 0} * @return The formatted number as a string. * @since 0.4.10 */ public static String format(Number number, String pattern, boolean isNullToZero) { return format(number, pattern, RoundingMode.HALF_UP, isNullToZero); } /** * Formats a given number according to a specified pattern with a specific rounding mode. * * @param number The number to be formatted. * @param pattern The pattern to be applied during formatting. * @param roundingMode The rounding mode to be used during formatting. * @param isNullToZero Is {@code null} to {@code 0} * @return The formatted number as a string. * @since 0.4.10 */ public static String format(Number number, String pattern, RoundingMode roundingMode, boolean isNullToZero) { if (number == null) return isNullToZero ? "0" : "null"; DecimalFormat df = new DecimalFormat(pattern); df.setRoundingMode(roundingMode); return df.format(number); } /** * Repeats a string a specified number of times. * * @param str The string to be repeated. * @param repeatTimes The number of times to repeat the string. * @return The repeated string. * @since 0.4.9 */ public static String repeat(String str, int repeatTimes) { if (str == null) return null; if (str.length() == 0 || repeatTimes <= 0) return ""; if (repeatTimes == 1) return str; if (repeatTimes > Integer.MAX_VALUE - 8) throw new IllegalArgumentException("Parameter `repeatTimes` must be <= (Integer.MAX_VALUE - 8), otherwise, the memory will overflow! "); return String.join("", Collections.nCopies(repeatTimes, str)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy