de.unkrig.commons.lang.StringUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of de-unkrig-commons Show documentation
Show all versions of de-unkrig-commons Show documentation
A versatile Java(TM) library that implements many useful container and utility classes.
/*
* de.unkrig.commons - A general-purpose Java class library
*
* Copyright (c) 2013, Arno Unkrig
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
* following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package de.unkrig.commons.lang;
import java.io.BufferedReader;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import de.unkrig.commons.lang.protocol.Predicate;
/**
* Various {@code java.lang.String}-related utility methods.
*/
public final
class StringUtil {
private
StringUtil() {}
/**
* Converts all {@code elements} to string and concatenates these, separated by the {@code glue}.
*/
public static String
join(Collection extends Object> elements, String glue) {
if (elements.size() == 0) return "";
if (elements.size() == 1) return String.valueOf(elements.iterator().next());
Iterator extends Object> it = elements.iterator();
StringBuilder sb = new StringBuilder();
sb.append(it.next());
while (it.hasNext()) sb.append(glue).append(it.next());
return sb.toString();
}
/**
* Naturally, {@link CharSequence} does not refine {@link Object#equals(Object)}. This method fills the gap.
*/
public static boolean
equals(CharSequence cs1, CharSequence cs2) {
int l1 = cs1.length(), l2 = cs2.length();
if (l1 != l2) return false;
for (int i = 0; i < l1; i++) {
if (cs1.charAt(i) != cs2.charAt(i)) return false;
}
return true;
}
/**
* Naturally, {@link CharSequence} does not extend {@link Comparable}. This method fills the gap.
*/
public static int
compareTo(CharSequence cs1, CharSequence cs2) {
int l1 = cs1.length(), l2 = cs1.length();
int n = Math.min(l1, l2);
for (int i = 0; i < n; i++) {
int diff = cs1.charAt(i) - cs2.charAt(i);
if (diff != 0) return diff;
}
return l1 - l2;
}
/**
* @return A string consisting of {@code n} times the character "{@code c}"
*/
public static String
repeat(int n, char c) {
if (n <= 0) return "";
char[] ca = new char[n];
Arrays.fill(ca, c);
return String.copyValueOf(ca);
}
/**
* @return A string consisting of {@code n} times the string "{@code s}"
*/
public static String
repeat(int n, String s) {
if (n <= 0) return "";
if (n == 1) return s;
int len = s.length();
char[] src = s.toCharArray();
char[] dst = new char[n * len];
for (int i = 0; i < n; i++) {
System.arraycopy(src, 0, dst, i * len, len);
}
return String.copyValueOf(dst);
}
/**
* @return Whether the given char sequences consists only of characters 0...32
*/
public static boolean
isBlank(CharSequence cs) {
for (int i = cs.length() - 1; i >= 0; i--) {
if (cs.charAt(i) > ' ') return false;
}
return true;
}
/**
* A predicate that evaluates its subject with {@link #isBlank(CharSequence)}.
*/
public static final Predicate
IS_BLANK = new Predicate() {
@Override public boolean evaluate(CharSequence subject) { return StringUtil.isBlank(subject); }
};
/** @return The string s, with the first letter converted to upper case */
public static String
firstLetterToUpperCase(String s) {
if (s.isEmpty() || !Character.isLowerCase(s.charAt(0))) return s;
return s.substring(0, 1).toUpperCase() + s.substring(1);
}
/** @return The string s, with the first letter converted to lower case */
public static String
firstLetterToLowerCase(String s) {
if (s.isEmpty() || !Character.isUpperCase(s.charAt(0))) return s;
return s.substring(0, 1).toLowerCase() + s.substring(1);
}
/**
* Wraps a char sequence as an iterable.
*/
public static Iterable
asIterable(final CharSequence subject) {
return new Iterable() {
@Override public Iterator iterator() { return StringUtil.iterator(subject); }
};
}
/**
* Returns an iterator that produces the characters of the subject, from index 0 through index {@code
* subject.length() - 1}.
*/
public static Iterator
iterator(final CharSequence subject) {
return new Iterator() {
int idx;
@Override public void
remove() { throw new NoSuchElementException("remove"); }
@Override public Character
next() {
if (this.idx >= subject.length()) throw new ArrayIndexOutOfBoundsException();
return subject.charAt(this.idx++);
}
@Override public boolean
hasNext() { return this.idx < subject.length(); }
};
}
/**
* Returns an iterator that produces the characters of the subject in reverse order, from index {@code
* subject.length() - 1} through index 0.
*/
public static Iterator
reverseIterator(final CharSequence subject) {
return new Iterator() {
int idx = subject.length();
@Override public void
remove() { throw new NoSuchElementException("remove"); }
@Override public Character
next() {
if (this.idx <= 0) throw new ArrayIndexOutOfBoundsException();
return subject.charAt(--this.idx);
}
@Override public boolean
hasNext() { return this.idx > 0; }
};
}
/**
* @return The s, with all trailing {@code '\r'} and {@code '\n'} chopped off
* @see BufferedReader#readLine()
*/
public static String
lessTrailingLineSeparators(String s) {
if (s.isEmpty()) return "";
int i = s.length() - 1;
// Examine the last character.
{
char c = s.charAt(i);
if (c != '\r' && c != '\n') return s;
}
// Find the last non-line-separator character.
for (i--; i >= 0; i--) {
char c = s.charAt(i);
if (c != '\r' && c != '\n') return s.substring(0, i + 1);
}
return "";
}
}