
com.github.hypfvieh.util.StringUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of java-utils Show documentation
Show all versions of java-utils Show documentation
A collection of utils commonly used in my projects.
Feel free to use it (or parts of it) in your own projects.
The newest version!
package com.github.hypfvieh.util;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
/**
* Utility class for String manipulation.
*
* @author hypfvieh
* @since v1.0 - 2016-06-29
*/
public final class StringUtil {
/** Characters used for random strings */
private static final char[] SYMBOLS;
static {
StringBuilder tmp = new StringBuilder();
for (char ch = '0'; ch <= '9'; ++ch)
tmp.append(ch);
for (char ch = 'a'; ch <= 'z'; ++ch)
tmp.append(ch);
for (char ch = 'A'; ch <= 'Z'; ++ch)
tmp.append(ch);
SYMBOLS = tmp.toString().toCharArray();
}
private StringUtil() {
}
/**
* Abbreviates a String using ellipses.
*
* @param _str string to abbrivate
* @param _length max length
* @return abbreviated string, original string if string length is lower or equal then desired length or null if input was null
*/
public static String abbreviate(String _str, int _length) {
if (_str == null) {
return null;
}
if (_str.length() <= _length) {
return _str;
}
String abbr = _str.substring(0, _length -3) + "...";
return abbr;
}
/**
* Tries to split a string in a smart way.
*
* String will be splitted by space and then recombined until each line has
* the given length or less than the given length, if the next token would cause
* the line to be longer than requested
*
* It is ensured that each line has a maximum length of _len, it could be short but never longer.
*
* @param _text text to split
* @param _len max length per line
* @return list or null if _text was null
*/
public static List smartWordSplit(String _text, int _len) {
if (_text == null) {
return null;
}
// if the given string is already shorter or equal to wanted length, return immediately
if (_text.length() <= _len) {
return TypeUtil.createList(_text);
}
List list = new ArrayList<>();
String[] result = _text.split("\\s");
for (int x=0; x _len) {
list.addAll(splitEqually(result[x], _len));
} else if (result[x].length() < _len) {
StringBuilder sb = new StringBuilder();
x = strAppender(result, sb, x, _len);
list.add(sb.toString());
} else {
list.add(result[x]);
}
}
return list;
}
/**
* Internally used by smartStringSplit to recombine the string until the expected length is reached.
*
* @param _text string array to process
* @param _sbResult resulting line
* @param _beginIdx start index of string array
* @param _len line length
* @return last position in string array or -1 if _text or _sbResult is null
*/
private static int strAppender(String[] _text, StringBuilder _sbResult, int _beginIdx, int _len) {
if (_text == null || _sbResult == null) {
return -1;
}
if (_beginIdx > _text.length) {
return _text.length;
}
int i = _beginIdx;
for (i = _beginIdx; i < _text.length; i++) { // current token length + current buffer length
if (_sbResult.length() < _len) {
int condition = _text[i].length() + _sbResult.length();
boolean firstOrLastToken = true;
if (i <= _text.length -1 && _sbResult.length() > 0) { // add one char (for trailing space) if result is not empty and we are not on the first token
condition += 1; // + 1 (for space)
firstOrLastToken = false;
}
if (condition <= _len) {
if (!firstOrLastToken) { // append a space if result is not empty and we are not on the first token
_sbResult.append(" ");
}
_sbResult.append(_text[i]);
} else {
i-=1;
break;
}
} else {
if (i > _beginIdx) {
i-=1;
}
break;
}
}
return i;
}
/**
* Splits a Text to equal parts.
* There is no detection of words, everything will be cut to the same length.
*
* @param _text text to split
* @param _len max length per line
* @return list of string splitted to _len or null if _text was null
*/
public static List splitEqually(String _text, int _len) {
if (_text == null) {
return null;
}
List ret = new ArrayList<>((_text.length() + _len - 1) / _len);
for (int start = 0; start < _text.length(); start += _len) {
ret.add(_text.substring(start, Math.min(_text.length(), start + _len)));
}
return ret;
}
/**
* Replace all placeholders in given string by value of the corresponding key in given Map.
*
* @param _searchStr search string
* @param _replacements replacement
* @return String or null if _searchStr was null
*/
public static String replaceByMap(String _searchStr, Map _replacements) {
if (_searchStr == null) {
return null;
}
if (_replacements == null || _replacements.isEmpty()) {
return _searchStr;
}
String str = _searchStr;
for (Entry entry : _replacements.entrySet()) {
str = str.replace(entry.getKey(), entry.getValue());
}
return str;
}
/**
* Lower case the first letter of the given string.
*
* @param _str string
* @return lowercased string
*/
public static String lowerCaseFirstChar(String _str) {
if (_str == null) {
return null;
}
if (_str.isEmpty()) {
return _str;
}
return _str.substring(0, 1).toLowerCase() + _str.substring(1);
}
/**
* Upper case the first letter of the given string.
*
* @param _str string
* @return uppercased string
*/
public static String upperCaseFirstChar(String _str) {
if (_str == null) {
return null;
}
if (_str.isEmpty()) {
return _str;
}
return _str.substring(0, 1).toUpperCase() + _str.substring(1);
}
/**
* Simple rot13 implementation.
*
* @param _input input to scramble
* @return scrambled input (null if input was null)
*/
public static String rot13(String _input) {
if (_input == null) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < _input.length(); i++) {
char c = _input.charAt(i);
if (c >= 'a' && c <= 'm') {
c += 13;
} else if (c >= 'A' && c <= 'M') {
c += 13;
} else if (c >= 'n' && c <= 'z') {
c -= 13;
} else if (c >= 'N' && c <= 'Z') {
c -= 13;
}
sb.append(c);
}
return sb.toString();
}
/**
* Checks if any of the given strings in _compare is equal to _str (case-insensitive).
* Will return true if both parameters are null or _str is null and _compare is empty.
*
* @param _str string to check
* @param _compare compare strings
* @return true if equal false otherwise
*/
public static boolean equalsIgnoreCaseAny(String _str, String... _compare) {
return equalsAny(true, _str, _compare); }
/**
* Checks if any of the given strings in _compare is equal to _str (case-sensitive).
* Will return true if both parameters are null or _str is null and _compare is empty.
*
* @param _str string to check
* @param _compare compare strings
* @return true if equal false otherwise
*/
public static boolean equalsAny(String _str, String... _compare) {
return equalsAny(false, _str, _compare);
}
/**
* Checks if any of the given strings in _compare is equal to _str (either case-insensitive or case-sensitive).
* Will return true if both parameters are null or _str is null and _compare is empty.
*
* @param _ignoreCase ignore case
* @param _str string to check
* @param _compare compare strings
* @return true if equal false otherwise
*/
public static boolean equalsAny(boolean _ignoreCase, String _str, String... _compare) {
if (_str == null && _compare == null || _compare.length == 0) {
return true;
} else if (_str == null) {
return false;
}
for (String cmp : _compare) {
if (_ignoreCase) {
if (cmp.equalsIgnoreCase(_str)) {
return true;
}
} else {
if (cmp.equals(_str)) {
return true;
}
}
}
return false;
}
/**
* Checks if the given String is either null or blank.
* Blank means:
*
* " " - true
* "" - true
* null - true
* " xx" - false
*
* @param _str string to test
* @return true if string is blank or null, false otherwise
*/
public static boolean isBlank(CharSequence _str) {
if (_str == null || _str.length() == 0) {
return true;
}
return IntStream.range(0, _str.length()).allMatch(i -> Character.isWhitespace(_str.charAt(i)));
}
/**
* Checks if the given String is either null or empty.
* Blank means:
*
* " " - false
* "" - true
* null - true
* " xx" - false
*
* @param _str string to test
* @return true if string is empty or null, false otherwise
*/
public static boolean isEmpty(CharSequence _str) {
return _str == null || _str.length() == 0;
}
/**
* Checks if given String is blank (see {@link #isBlank(String)}.
* If String is blank, the given default is returned, otherwise the String is returned.
* @param _str string to check
* @param _default default in case of blank string
* @return _str or _default
*/
public static String defaultIfBlank(String _str, String _default) {
return isBlank(_str) ? _default : _str;
}
/**
* Generate a simple (cryptographic insecure) random string.
* @param _length length of random string
* @return random string or empty string if _length <= 0
*/
public static String randomString(int _length) {
if (_length <= 0) {
return "";
}
Random random = new Random();
char[] buf = new char[_length];
for (int idx = 0; idx < buf.length; ++idx)
buf[idx] = SYMBOLS[random.nextInt(SYMBOLS.length)];
return new String(buf);
}
/**
* Combines the Strings in _string using _delimiter.
* @param _delimiter delimiting string
* @param _strings strings to join
* @return null if _strings is null, concatenated string otherwise
*/
public static String join(String _delimiter, List _strings) {
if (_strings == null) {
return null;
}
if (_delimiter == null) {
_delimiter = "";
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < _strings.size(); i++) {
sb.append(_strings.get(i));
if (i < _strings.size() - 1) { // only append delimiter if this is not the last token
sb.append(_delimiter);
}
}
return sb.toString();
}
/**
* Combines the Strings in _string using _delimiter.
* @param _delimiter delimiting string
* @param _strings string to join
* @return null if _strings is null, concatenated string otherwise
*/
public static String join(String _delimiter, String[] _strings) {
return join(_delimiter, Arrays.asList(_strings));
}
/**
* Converts a camel-case string to an upper-case string
* where each upper-case character except the first in
* the input string is preceded by an underscore in the
* output string.
* Empty or null strings are returned as-is.
*
* convertCamelToUpperCase(null) = null
* convertCamelToUpperCase("") = ""
* convertCamelToUpperCase(" ") = " "
* convertCamelToUpperCase("Hello") = "HELLO"
* convertCamelToUpperCase("HELLO") = "HELLO"
* convertCamelToUpperCase("AcmeCompany") = "ACME_COMPANY"
*
* @param _str camel-case string
* @return upper-case string
*/
public static String convertCamelToUpperCase(String _str) {
if (isEmpty(_str) || isAllUpperCase(_str)) {
return _str;
}
StringBuffer sb = new StringBuffer(String.valueOf(_str.charAt(0)).toUpperCase());
for (int i = 1; i < _str.length(); i++) {
char c = _str.charAt(i);
if (c >= 'A' && c <= 'Z') {
sb.append('_');
}
sb.append(c);
}
return sb.toString().toUpperCase();
}
/**
* Tries to convert upper-case string to camel-case.
* The given string will be analyzed and all string parts preceded by an underline character will be
* converted to upper-case, all other following characters to lower-case.
* @param _str string to convert
* @return converted string or original string if there was nothing to do
*/
public static String convertUpperToCamelCase(String _str) {
if (_str == null || isBlank(_str)) {
return _str;
} else if (!_str.contains("_")) {
return (_str.charAt(0) + "").toUpperCase() + _str.substring(1);
}
StringBuffer sb = new StringBuffer(String.valueOf(_str.charAt(0)).toUpperCase());
for (int i = 1; i < _str.length(); i++) {
char c = _str.charAt(i);
if (c == '_') {
i++; // get next character and convert to upper case
c = String.valueOf(_str.charAt(i)).toUpperCase().charAt(0);
} else {
c = String.valueOf(c).toLowerCase().charAt(0);
}
sb.append(c);
}
return sb.toString();
}
/**
* Checks if the given String is in all upper-case.
* @param _str string to check
* @return true if upper-case, false otherwise. Also false if string is null or empty.
*/
public static boolean isAllUpperCase(String _str) {
return isEmpty(_str) || !_str.matches(".*[a-z].*");
}
/**
* Checks if any of the given strings in _args is contained in _str, case-insensitve.
* @param _str string to check
* @param _args patterns to find
* @return true if any string in _args is found in _str, false if not or _str/_args is null
*/
public static boolean containsAnyIgnoreCase(String _str, String... _args) {
return containsAny(true, _str, _args);
}
/**
* Checks if any of the given strings in _args is contained in _str, case-sensitive.
*
* @param _str string to check
* @param _args patterns to find
* @return true if any string in _args is found in _str, false if not or _str/_args is null
*/
public static boolean containsAny(String _str, String... _args) {
return containsAny(false, _str, _args);
}
/**
* Checks if any of the given strings in _args is contained in _str.
* @param _ignoreCase true to ignore case, false to be case sensitive
* @param _str string to check
* @param _args patterns to find
* @return true if any string in _args is found in _str, false if not or _str/_args is null
*/
public static boolean containsAny(boolean _ignoreCase, String _str, String... _args) {
if (_str == null || _args == null || _args.length == 0) {
return false;
}
String heystack = _str;
if (_ignoreCase) {
heystack = _str.toLowerCase();
}
for (String s : _args) {
String needle = _ignoreCase ? s.toLowerCase() : s;
if (heystack.contains(needle)) {
return true;
}
}
return false;
}
/**
* Checks if given string in _str ends with any of the given strings in _args.
* @param _ignoreCase true to ignore case, false to be case sensitive
* @param _str string to check
* @param _args patterns to find
* @return true if given string in _str ends with any of the given strings in _args, false if not or _str/_args is null
*/
public static boolean endsWithAny(boolean _ignoreCase, String _str, String... _args) {
if (_str == null || _args == null || _args.length == 0) {
return false;
}
String heystack = _str;
if (_ignoreCase) {
heystack = _str.toLowerCase();
}
for (String s : _args) {
String needle = _ignoreCase ? s.toLowerCase() : s;
if (heystack.endsWith(needle)) {
return true;
}
}
return false;
}
/**
* Checks if given string in _str starts with any of the given strings in _args.
* @param _ignoreCase true to ignore case, false to be case sensitive
* @param _str string to check
* @param _args patterns to find
* @return true if given string in _str starts with any of the given strings in _args, false if not or _str/_args is null
*/
public static boolean startsWithAny(boolean _ignoreCase, String _str, String... _args) {
if (_str == null || _args == null || _args.length == 0) {
return false;
}
String heystack = _str;
if (_ignoreCase) {
heystack = _str.toLowerCase();
}
for (String s : _args) {
String needle = _ignoreCase ? s.toLowerCase() : s;
if (heystack.startsWith(needle)) {
return true;
}
}
return false;
}
/**
* Repeats the given string pattern for the given times.
* @param _str string to repeat
* @param _count number of repetitions
* @return repeated string or null if pattern was null or count was <= 0
*/
public static String repeat(String _str, int _count) {
if (_str == null || _count <= 0) {
return null;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < _count; i++) {
sb.append(_str);
}
return sb.toString();
}
/**
* Right-pads a string with spaces (' ').
* The String is padded to the size of {@code _size}.
*
*
* StringUtil.rightPad(null, *) = null
* StringUtil.rightPad("", 3) = " "
* StringUtil.rightPad("bat", 3) = "bat"
* StringUtil.rightPad("bat", 5) = "bat "
* StringUtil.rightPad("bat", 1) = "bat"
* StringUtil.rightPad("bat", -1) = "bat"
*
*
* @param _str the String to pad out, may be null
* @param _size the size to pad to
* @param _padChar the padding character
* @return right-padded String or original String if no padding is necessary
*/
public static String rightPad(String _str, int _size, String _padChar) {
if (_str == null) {
return null;
}
int pads = _size - _str.length();
if (pads <= 0) {
return _str;
}
return _str.concat(repeat(_padChar, pads));
}
/**
* Split a String by the given delimiting char.
* @param _str string to split
* @param _separatorChar delimiting char to use
* @return null if _str is null, array (maybe empty) otherwise
*/
public static String[] split(String _str, char _separatorChar) {
return split(_str, Character.toString(_separatorChar));
}
/**
* Split a String by the given delimiting char.
* @param _str string to split
* @param _separatorStr delimiting String to use
* @return null if _str is null, array (maybe empty) otherwise
*/
public static String[] split(String _str, String _separatorStr) {
if (_str == null) {
return null;
}
List list = splitToList(_str, _separatorStr);
return list.toArray(new String[list.size()]);
}
/**
* Split string by whitespace.
* @param _str string to split
* @return null if _str is null, array (maybe empty) otherwise
*/
public static String[] split(String _str) {
return split(_str, ' ');
}
/**
* Split given String using given delimiting char.
*
* @param _str string to split
* @param _separatorChar char to use as delimiter
* @return list of String tokens, null if _str is null or empty list
*/
public static List splitToList(String _str, char _separatorChar) {
return splitToList(_str, Character.toString(_separatorChar));
}
/**
* Split given String using the given delimiting string.
*
* @param _str string to split
* @param _separatorStr string to us as delimiter
* @return list of String tokens, null if _str is null or empty list
*/
public static List splitToList(String _str, String _separatorStr) {
if (_str == null) {
return null;
}
List list = new ArrayList<>();
StringTokenizer st = new StringTokenizer(_str, _separatorStr);
while (st.hasMoreTokens()) {
list.add(st.nextToken());
}
return list;
}
/**
* Mask the given string with the given pattern starting at given start and ending on given end of string.
*
* If _str is null or _maskStr is null or empty, null is returned.
*
* If _maskBgn is lower than 0 or _maskLength is lower than 0
* or _maskRpt minus _maskBgn is lower than 0, null is returned.
*
* If _maskBgn is bigger than the length of _str, the original String is returned.
* If _maskRpt is bigger than the length of _str, length of _str is used.
*
* @param _str string to mask
* @param _maskStr mask to use
* @param _maskBgn offset to start at (0 based, inclusive)
* @param _maskRpt repetitions of _maskStr
*
* @return masked String or null
*/
public static String mask(String _str, String _maskStr, int _maskBgn, int _maskRpt) {
if (_str == null || _maskStr == null || _maskStr.isEmpty()) {
return null;
}
if (_maskBgn < 0 || _maskRpt <= 0 || _maskRpt - _maskBgn < 0) {
return _str;
}
if (_maskBgn > _str.length()) {
return _str;
}
StringBuilder sb = new StringBuilder();
int maskCnt = 0;
for (int i = 0; i < _str.length(); i++) {
if (i < _maskBgn) {
sb.append(_str.charAt(i));
continue;
}
if (maskCnt < _maskRpt) {
sb.append(_maskStr);
maskCnt++;
} else {
sb.append(_str.charAt(i));
}
}
return sb.toString();
}
/**
* Converts a snake-case-string to camel case string.
*
* Eg. this_is_snake_case → thisIsSnakeCase
* @param _input string
* @return camel case string or input if nothing todo. Returns null if input was null.
*/
public static String snakeToCamelCase(String _input) {
if (isBlank(_input)) {
return _input;
}
Pattern compile = Pattern.compile("_[a-zA-Z]");
Matcher matcher = compile.matcher(_input);
String result = _input;
while (matcher.find()) {
String match = matcher.group();
String replacement = match.replace("_", "");
replacement = replacement.toUpperCase();
result = result.replaceFirst(match, replacement);
}
return result;
}
/**
* Concats all strings using the separator as delimiter.
* Will exclude all null values and optionally ignore empty values.
*
* @param _ignoreEmpty true to ignore empty strings
* @param _separator separator to add between each string
* @param _parts parts to concat
*
* @return concatinated string, null if input is null
*/
public static String concatStrings(boolean _ignoreEmpty, String _separator, String... _parts) {
if (_parts == null) {
return null;
}
StringBuilder allParts = new StringBuilder();
for (int i = 0; i < _parts.length; i++) {
if (_parts[i] == null) {
continue;
}
if (_ignoreEmpty && _parts[i].isEmpty()) {
continue;
}
allParts.append(_parts[i]);
if (!_parts[i].endsWith(_separator)) {
allParts.append(_separator);
}
}
if (allParts.toString().isEmpty()) {
return "";
}
return allParts.toString().substring(0, allParts.lastIndexOf(_separator));
}
/**
* Checks that the specified string is not {@code blank}.
* This method is designed primarily for doing parameter validation in methods
* and constructors.
*
* @param _str the sequence to check for blankness
* @param _message exception message if check fails
* @return {@code _str} if not {@code blank}
* @throws IllegalArgumentException if {@code _str} is {@code blank}
*/
public static T requireNonBlank(T _str, String _message) {
if (isBlank(_str)) {
throw new IllegalArgumentException(_message);
}
return _str;
}
public static T requireNonBlank(T _str) {
return requireNonBlank(_str, "String may not be blank");
}
/**
* Checks that the specified string is not {@code empty}.
* This method is designed primarily for doing parameter validation in methods
* and constructors.
*
* @param _str the sequence to check for emptiness
* @param _message exception message if check fails
* @return {@code _str} if not {@code empty}
* @throws IllegalArgumentException if {@code _str} is {@code empty}
*/
public static T requireNonEmpty(T _str, String _message) {
if (isEmpty(_str)) {
throw new IllegalArgumentException(_message);
}
return _str;
}
public static T requireNonEmpty(T _str) {
return requireNonEmpty(_str, "String may not be empty");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy