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

cn.hutool.core.text.StrBuilder Maven / Gradle / Ivy

There is a newer version: 5.8.33
Show newest version
package cn.hutool.core.text;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;

import java.io.Serializable;
import java.util.Arrays;

/**
 * 可复用的字符串生成器,非线程安全
* TODO 6.x移除此类,java8的StringBuilder非常完善了,无需重写。 * * @author Looly * @since 4.0.0 */ public class StrBuilder implements CharSequence, Appendable, Serializable { private static final long serialVersionUID = 6341229705927508451L; /** * 默认容量 */ public static final int DEFAULT_CAPACITY = 16; /** * 存放的字符数组 */ private char[] value; /** * 当前指针位置,或者叫做已经加入的字符数,此位置总在最后一个字符之后 */ private int position; /** * 创建字符串构建器 * * @return this */ public static StrBuilder create() { return new StrBuilder(); } /** * 创建字符串构建器 * * @param initialCapacity 初始容量 * @return this */ public static StrBuilder create(int initialCapacity) { return new StrBuilder(initialCapacity); } /** * 创建字符串构建器 * * @param strs 初始字符串 * @return this * @since 4.0.1 */ public static StrBuilder create(CharSequence... strs) { return new StrBuilder(strs); } // ------------------------------------------------------------------------------------ Constructor start /** * 构造 */ public StrBuilder() { this(DEFAULT_CAPACITY); } /** * 构造 * * @param initialCapacity 初始容量 */ public StrBuilder(int initialCapacity) { value = new char[initialCapacity]; } /** * 构造 * * @param strs 初始字符串 * @since 4.0.1 */ public StrBuilder(CharSequence... strs) { this(ArrayUtil.isEmpty(strs) ? DEFAULT_CAPACITY : (totalLength(strs) + DEFAULT_CAPACITY)); for (CharSequence str : strs) { append(str); } } // ------------------------------------------------------------------------------------ Constructor end // ------------------------------------------------------------------------------------ Append /** * 追加对象,对象会被转换为字符串 * * @param obj 对象 * @return this */ public StrBuilder append(Object obj) { return insert(this.position, obj); } /** * 追加一个字符 * * @param c 字符 * @return this */ @Override public StrBuilder append(char c) { return insert(this.position, c); } /** * 追加一个字符数组 * * @param src 字符数组 * @return this */ public StrBuilder append(char[] src) { if (ArrayUtil.isEmpty(src)) { return this; } return append(src, 0, src.length); } /** * 追加一个字符数组 * * @param src 字符数组 * @param srcPos 开始位置(包括) * @param length 长度 * @return this */ public StrBuilder append(char[] src, int srcPos, int length) { return insert(this.position, src, srcPos, length); } @Override public StrBuilder append(CharSequence csq) { return insert(this.position, csq); } @Override public StrBuilder append(CharSequence csq, int start, int end) { return insert(this.position, csq, start, end); } // ------------------------------------------------------------------------------------ Insert /** * 追加对象,对象会被转换为字符串 * * @param index 插入位置 * @param obj 对象 * @return this */ public StrBuilder insert(int index, Object obj) { if (obj instanceof CharSequence) { return insert(index, (CharSequence) obj); } return insert(index, Convert.toStr(obj)); } /** * 插入指定字符 * * @param index 位置 * @param c 字符 * @return this */ public StrBuilder insert(int index, char c) { if(index < 0){ index = this.position + index; } if ((index < 0)) { throw new StringIndexOutOfBoundsException(index); } moveDataAfterIndex(index, 1); value[index] = c; this.position = Math.max(this.position, index) + 1; return this; } /** * 指定位置插入数据
* 如果插入位置为当前位置,则定义为追加
* 如果插入位置大于当前位置,则中间部分补充空格 * * @param index 插入位置 * @param src 源数组 * @return this */ public StrBuilder insert(int index, char[] src) { if (ArrayUtil.isEmpty(src)) { return this; } return insert(index, src, 0, src.length); } /** * 指定位置插入数据
* 如果插入位置为当前位置,则定义为追加
* 如果插入位置大于当前位置,则中间部分补充空格 * * @param index 插入位置 * @param src 源数组 * @param srcPos 位置 * @param length 长度 * @return this */ public StrBuilder insert(int index, char[] src, int srcPos, int length) { if (ArrayUtil.isEmpty(src) || srcPos > src.length || length <= 0) { return this; } if(index < 0){ index = this.position + index; } if ((index < 0)) { throw new StringIndexOutOfBoundsException(index); } if (srcPos < 0) { srcPos = 0; } else if (srcPos + length > src.length) { // 长度越界,只截取最大长度 length = src.length - srcPos; } moveDataAfterIndex(index, length); // 插入数据 System.arraycopy(src, srcPos, value, index, length); this.position = Math.max(this.position, index) + length; return this; } /** * 指定位置插入字符串的某个部分
* 如果插入位置为当前位置,则定义为追加
* 如果插入位置大于当前位置,则中间部分补充空格 * * @param index 位置 * @param csq 字符串 * @return this */ public StrBuilder insert(int index, CharSequence csq) { if(index < 0){ index = this.position + index; } if ((index < 0)) { throw new StringIndexOutOfBoundsException(index); } if (null == csq) { csq = StrUtil.EMPTY; } int len = csq.length(); moveDataAfterIndex(index, csq.length()); if (csq instanceof String) { ((String) csq).getChars(0, len, this.value, index); } else if (csq instanceof StringBuilder) { ((StringBuilder) csq).getChars(0, len, this.value, index); } else if (csq instanceof StringBuffer) { ((StringBuffer) csq).getChars(0, len, this.value, index); } else if (csq instanceof StrBuilder) { ((StrBuilder) csq).getChars(0, len, this.value, index); } else { for (int i = 0, j = this.position; i < len; i++, j++) { this.value[j] = csq.charAt(i); } } this.position = Math.max(this.position, index) + len; return this; } /** * 指定位置插入字符串的某个部分
* 如果插入位置为当前位置,则定义为追加
* 如果插入位置大于当前位置,则中间部分补充空格 * * @param index 位置 * @param csq 字符串 * @param start 字符串开始位置(包括) * @param end 字符串结束位置(不包括) * @return this */ public StrBuilder insert(int index, CharSequence csq, int start, int end) { if (csq == null) { csq = "null"; } final int csqLen = csq.length(); if (start > csqLen) { return this; } if (start < 0) { start = 0; } if (end > csqLen) { end = csqLen; } if (start >= end) { return this; } if(index < 0){ index = this.position + index; } if ((index < 0)) { throw new StringIndexOutOfBoundsException(index); } final int length = end - start; moveDataAfterIndex(index, length); for (int i = start, j = this.position; i < end; i++, j++) { value[j] = csq.charAt(i); } this.position = Math.max(this.position, index) + length; return this; } // ------------------------------------------------------------------------------------ Others /** * 将指定段的字符列表写出到目标字符数组中 * * @param srcBegin 起始位置(包括) * @param srcEnd 结束位置(不包括) * @param dst 目标数组 * @param dstBegin 目标起始位置(包括) * @return this */ public StrBuilder getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) { if (srcBegin < 0) { srcBegin = 0; } if (srcEnd < 0) { srcEnd = 0; } else if (srcEnd > this.position) { srcEnd = this.position; } if (srcBegin > srcEnd) { throw new StringIndexOutOfBoundsException("srcBegin > srcEnd"); } System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); return this; } /** * 是否有内容 * * @return 是否有内容 */ public boolean hasContent() { return position > 0; } /** * 是否为空 * * @return 是否为空 */ public boolean isEmpty() { return position == 0; } /** * 删除全部字符,位置归零 * * @return this */ public StrBuilder clear() { return reset(); } /** * 删除全部字符,位置归零 * * @return this */ public StrBuilder reset() { this.position = 0; return this; } /** * 删除到指定位置
* 如果新位置小于等于0,则删除全部 * * @param newPosition 新的位置,不包括这个位置 * @return this */ public StrBuilder delTo(int newPosition) { if (newPosition < 0) { newPosition = 0; } return del(newPosition, this.position); } /** * 删除指定长度的字符,规则如下: * *
	 * 1、end大于等于最大长度,结束按照最大长度计算,相当于删除start之后虽有部分(性能最好)
	 * 2、end小于start时,抛出StringIndexOutOfBoundsException
	 * 3、start小于0 按照0处理
	 * 4、start等于end不处理
	 * 5、start和end都位于长度区间内,删除这段内容(内存拷贝)
	 * 
* * @param start 开始位置,负数按照0处理(包括) * @param end 结束位置,超出最大长度按照最大长度处理(不包括) * @return this * @throws StringIndexOutOfBoundsException 当start > end抛出此异常 */ public StrBuilder del(int start, int end) throws StringIndexOutOfBoundsException { if (start < 0) { start = 0; } if (end >= this.position) { // end在边界及以外,相当于删除后半部分 this.position = start; return this; } else if (end < 0) { // start和end都为0的情况下表示删除全部 end = 0; } int len = end - start; // 截取中间部分,需要将后半部分复制到删除的开始位置 if (len > 0) { System.arraycopy(value, start + len, value, start, this.position - end); this.position -= len; } else if (len < 0) { throw new StringIndexOutOfBoundsException("Start is greater than End."); } return this; } /** * 生成字符串 * * @param isReset 是否重置,重置后相当于空的构建器 * @return 生成的字符串 */ public String toString(boolean isReset) { if (position > 0) { final String s = new String(value, 0, position); if (isReset) { reset(); } return s; } return StrUtil.EMPTY; } /** * 重置并返回生成的字符串 * * @return 字符串 */ public String toStringAndReset() { return toString(true); } /** * 生成字符串 */ @Override public String toString() { return toString(false); } @Override public int length() { return this.position; } @Override public char charAt(int index) { if(index < 0){ index = this.position + index; } if ((index < 0) || (index > this.position)) { throw new StringIndexOutOfBoundsException(index); } return this.value[index]; } @Override public CharSequence subSequence(int start, int end) { return subString(start, end); } /** * 返回自定段的字符串 * * @param start 开始位置(包括) * @return this */ public String subString(int start) { return subString(start, this.position); } /** * 返回自定段的字符串 * * @param start 开始位置(包括) * @param end 结束位置(不包括) * @return this */ public String subString(int start, int end) { return new String(this.value, start, end - start); } // ------------------------------------------------------------------------------------ Private method start /** * 指定位置之后的数据后移指定长度 * * @param index 位置 * @param length 位移长度 */ private void moveDataAfterIndex(int index, int length) { ensureCapacity(Math.max(this.position, index) + length); if (index < this.position) { // 插入位置在已有数据范围内,后移插入位置之后的数据 System.arraycopy(this.value, index, this.value, index + length, this.position - index); } else if (index > this.position) { // 插入位置超出范围,则当前位置到index清除为空格 Arrays.fill(this.value, this.position, index, StrUtil.C_SPACE); } // 不位移 } /** * 确认容量是否够用,不够用则扩展容量 * * @param minimumCapacity 最小容量 */ private void ensureCapacity(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { expandCapacity(minimumCapacity); } } /** * 扩展容量
* 首先对容量进行二倍扩展,如果小于最小容量,则扩展为最小容量 * * @param minimumCapacity 需要扩展的最小容量 */ private void expandCapacity(int minimumCapacity) { int newCapacity = (value.length << 1) + 2; // overflow-conscious code if (newCapacity - minimumCapacity < 0) { newCapacity = minimumCapacity; } if (newCapacity < 0) { throw new OutOfMemoryError("Capacity is too long and max than Integer.MAX"); } value = Arrays.copyOf(value, newCapacity); } /** * 给定字符串数组的总长度
* null字符长度定义为0 * * @param strs 字符串数组 * @return 总长度 * @since 4.0.1 */ private static int totalLength(CharSequence... strs) { int totalLength = 0; for (CharSequence str : strs) { totalLength += (null == str ? 0 : str.length()); } return totalLength; } // ------------------------------------------------------------------------------------ Private method end }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy