diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 2ade95888..2c2bea9e1 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + Avoid String allocation in StrBuilder.append(CharSequence) Update maven-checkstyle-plugin to 2.14 Update org.easymock:easymock to 3.3.1 Update maven-pmd-plugin to 3.4 diff --git a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java index 23e40d6fb..103b04035 100644 --- a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java +++ b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java @@ -505,7 +505,10 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build public StrBuilder append(final Object obj) { if (obj == null) { return appendNull(); - } + } + if (obj instanceof CharSequence) { + return append((CharSequence) obj); + } return append(obj.toString()); } @@ -521,7 +524,19 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build public StrBuilder append(final CharSequence seq) { if (seq == null) { return appendNull(); - } + } + if (seq instanceof StrBuilder) { + return append((StrBuilder) seq); + } + if (seq instanceof StringBuilder) { + return append((StringBuilder) seq); + } + if (seq instanceof StringBuffer) { + return append((StringBuffer) seq); + } + if (seq instanceof CharBuffer) { + return append((CharBuffer) seq); + } return append(seq.toString()); } @@ -606,6 +621,62 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build return append(String.format(format, objs)); } + /** + * Appends the contents of a char buffer to this string builder. + * Appending null will call {@link #appendNull()}. + * + * @param buf the char buffer to append + * @return this, to enable chaining + * @since 3.4 + */ + public StrBuilder append(final CharBuffer buf) { + if (buf == null) { + return appendNull(); + } + if (buf.hasArray()) { + final int length = buf.remaining(); + final int len = length(); + ensureCapacity(len + length); + System.arraycopy(buf.array(), buf.arrayOffset() + buf.position(), buffer, len, length); + size += length; + } else { + append(buf.toString()); + } + return this; + } + + /** + * Appends the contents of a char buffer to this string builder. + * Appending null will call {@link #appendNull()}. + * + * @param buf the char buffer to append + * @param startIndex the start index, inclusive, must be valid + * @param length the length to append, must be valid + * @return this, to enable chaining + * @since 3.4 + */ + public StrBuilder append(final CharBuffer buf, final int startIndex, final int length) { + if (buf == null) { + return appendNull(); + } + if (buf.hasArray()) { + final int totalLength = buf.remaining(); + if (startIndex < 0 || startIndex > totalLength) { + throw new StringIndexOutOfBoundsException("startIndex must be valid"); + } + if (length < 0 || (startIndex + length) > totalLength) { + throw new StringIndexOutOfBoundsException("length must be valid"); + } + final int len = length(); + ensureCapacity(len + length); + System.arraycopy(buf.array(), buf.arrayOffset() + buf.position() + startIndex, buffer, len, length); + size += length; + } else { + append(buf.toString(), startIndex, length); + } + return this; + } + /** * Appends a string buffer to this string builder. * Appending null will call {@link #appendNull()}. diff --git a/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java b/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java index ec959aff9..2da4cf1ef 100644 --- a/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java +++ b/src/test/java/org/apache/commons/lang3/text/StrBuilderTest.java @@ -1938,6 +1938,21 @@ public class StrBuilderTest { assertEquals(sb.toString(), sb.build()); } + //----------------------------------------------------------------------- + @Test + public void testAppendCharBuffer() { + final StrBuilder sb1 = new StrBuilder(); + final CharBuffer buf = CharBuffer.allocate(10); + buf.append("0123456789"); + buf.flip(); + sb1.append(buf); + assertEquals("0123456789", sb1.toString()); + + final StrBuilder sb2 = new StrBuilder(); + sb2.append(buf, 1, 8); + assertEquals("12345678", sb2.toString()); + } + //----------------------------------------------------------------------- @Test public void testAppendToWriter() throws Exception {