8333396: Use StringBuilder internally for java.text.Format.* formatting

Reviewed-by: naoto, liach, jlu
This commit is contained in:
lingjun.cg 2024-07-22 02:01:08 +00:00
parent fd741a88e8
commit 4da9915875
16 changed files with 764 additions and 73 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -54,7 +54,7 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
} }
public void formatted(Format.Field attr, Object value, int start, int end, public void formatted(Format.Field attr, Object value, int start, int end,
StringBuffer buffer) { Format.StringBuf buffer) {
if (start != end) { if (start != end) {
if (start < size) { if (start < size) {
// Adjust attributes of existing runs // Adjust attributes of existing runs
@ -93,7 +93,7 @@ class CharacterIteratorFieldDelegate implements Format.FieldDelegate {
} }
public void formatted(int fieldID, Format.Field attr, Object value, public void formatted(int fieldID, Format.Field attr, Object value,
int start, int end, StringBuffer buffer) { int start, int end, Format.StringBuf buffer) {
formatted(attr, value, start, end, buffer); formatted(attr, value, start, end, buffer);
} }

View File

@ -514,7 +514,13 @@ public class ChoiceFormat extends NumberFormat {
@Override @Override
public StringBuffer format(long number, StringBuffer toAppendTo, public StringBuffer format(long number, StringBuffer toAppendTo,
FieldPosition status) { FieldPosition status) {
return format((double)number, toAppendTo, status); return format((double) number, StringBufFactory.of(toAppendTo), status).asStringBuffer();
}
@Override
StringBuf format(long number, StringBuf toAppendTo,
FieldPosition status) {
return format((double) number, toAppendTo, status);
} }
/** /**
@ -531,6 +537,12 @@ public class ChoiceFormat extends NumberFormat {
@Override @Override
public StringBuffer format(double number, StringBuffer toAppendTo, public StringBuffer format(double number, StringBuffer toAppendTo,
FieldPosition status) { FieldPosition status) {
return format(number, StringBufFactory.of(toAppendTo), status).asStringBuffer();
}
@Override
StringBuf format(double number, StringBuf toAppendTo,
FieldPosition status) {
// find the number // find the number
int i; int i;
for (i = 0; i < choiceLimits.length; ++i) { for (i = 0; i < choiceLimits.length; ++i) {

View File

@ -544,6 +544,35 @@ public final class CompactNumberFormat extends NumberFormat {
throw new IllegalArgumentException("Cannot format null as a number"); throw new IllegalArgumentException("Cannot format null as a number");
} }
if (number instanceof Long || number instanceof Integer
|| number instanceof Short || number instanceof Byte
|| number instanceof AtomicInteger
|| number instanceof AtomicLong
|| (number instanceof BigInteger
&& ((BigInteger) number).bitLength() < 64)) {
return format(((Number) number).longValue(), toAppendTo,
fieldPosition);
} else if (number instanceof BigDecimal) {
return format((BigDecimal) number, StringBufFactory.of(toAppendTo), fieldPosition).asStringBuffer();
} else if (number instanceof BigInteger) {
return format((BigInteger) number, StringBufFactory.of(toAppendTo), fieldPosition).asStringBuffer();
} else if (number instanceof Number) {
return format(((Number) number).doubleValue(), toAppendTo, fieldPosition);
} else {
throw new IllegalArgumentException("Cannot format "
+ number.getClass().getName() + " as a number");
}
}
@Override
StringBuf format(Object number,
StringBuf toAppendTo,
FieldPosition fieldPosition) {
if (number == null) {
throw new IllegalArgumentException("Cannot format null as a number");
}
if (number instanceof Long || number instanceof Integer if (number instanceof Long || number instanceof Integer
|| number instanceof Short || number instanceof Byte || number instanceof Short || number instanceof Byte
|| number instanceof AtomicInteger || number instanceof AtomicInteger
@ -591,12 +620,21 @@ public final class CompactNumberFormat extends NumberFormat {
public StringBuffer format(double number, StringBuffer result, public StringBuffer format(double number, StringBuffer result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, StringBufFactory.of(result), fieldPosition.getFieldDelegate()).asStringBuffer();
}
@Override
StringBuf format(double number, StringBuf result,
FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0); fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0); fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate()); return format(number, result, fieldPosition.getFieldDelegate());
} }
private StringBuffer format(double number, StringBuffer result, private StringBuf format(double number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
boolean nanOrInfinity = decimalFormat.handleNaN(number, result, delegate); boolean nanOrInfinity = decimalFormat.handleNaN(number, result, delegate);
@ -681,12 +719,21 @@ public final class CompactNumberFormat extends NumberFormat {
public StringBuffer format(long number, StringBuffer result, public StringBuffer format(long number, StringBuffer result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, StringBufFactory.of(result), fieldPosition.getFieldDelegate()).asStringBuffer();
}
@Override
StringBuf format(long number, StringBuf result,
FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0); fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0); fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate()); return format(number, result, fieldPosition.getFieldDelegate());
} }
private StringBuffer format(long number, StringBuffer result, FieldDelegate delegate) { private StringBuf format(long number, StringBuf result, FieldDelegate delegate) {
boolean isNegative = (number < 0); boolean isNegative = (number < 0);
if (isNegative) { if (isNegative) {
number = -number; number = -number;
@ -757,14 +804,14 @@ public final class CompactNumberFormat extends NumberFormat {
* of the prefix and the suffix fields can be * of the prefix and the suffix fields can be
* obtained using {@link NumberFormat.Field#PREFIX} * obtained using {@link NumberFormat.Field#PREFIX}
* and {@link NumberFormat.Field#SUFFIX} respectively. * and {@link NumberFormat.Field#SUFFIX} respectively.
* @return the {@code StringBuffer} passed in as {@code result} * @return the {@code StringBuf} passed in as {@code result}
* @throws ArithmeticException if rounding is needed with rounding * @throws ArithmeticException if rounding is needed with rounding
* mode being set to {@code RoundingMode.UNNECESSARY} * mode being set to {@code RoundingMode.UNNECESSARY}
* @throws NullPointerException if any of the given parameter * @throws NullPointerException if any of the given parameter
* is {@code null} * is {@code null}
* @see FieldPosition * @see FieldPosition
*/ */
private StringBuffer format(BigDecimal number, StringBuffer result, private StringBuf format(BigDecimal number, StringBuf result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
Objects.requireNonNull(number); Objects.requireNonNull(number);
@ -773,7 +820,7 @@ public final class CompactNumberFormat extends NumberFormat {
return format(number, result, fieldPosition.getFieldDelegate()); return format(number, result, fieldPosition.getFieldDelegate());
} }
private StringBuffer format(BigDecimal number, StringBuffer result, private StringBuf format(BigDecimal number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
boolean isNegative = number.signum() == -1; boolean isNegative = number.signum() == -1;
@ -843,14 +890,14 @@ public final class CompactNumberFormat extends NumberFormat {
* prefix and the suffix fields can be obtained * prefix and the suffix fields can be obtained
* using {@link NumberFormat.Field#PREFIX} and * using {@link NumberFormat.Field#PREFIX} and
* {@link NumberFormat.Field#SUFFIX} respectively. * {@link NumberFormat.Field#SUFFIX} respectively.
* @return the {@code StringBuffer} passed in as {@code result} * @return the {@code StringBuf} passed in as {@code result}
* @throws ArithmeticException if rounding is needed with rounding * @throws ArithmeticException if rounding is needed with rounding
* mode being set to {@code RoundingMode.UNNECESSARY} * mode being set to {@code RoundingMode.UNNECESSARY}
* @throws NullPointerException if any of the given parameter * @throws NullPointerException if any of the given parameter
* is {@code null} * is {@code null}
* @see FieldPosition * @see FieldPosition
*/ */
private StringBuffer format(BigInteger number, StringBuffer result, private StringBuf format(BigInteger number, StringBuf result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
Objects.requireNonNull(number); Objects.requireNonNull(number);
@ -859,7 +906,7 @@ public final class CompactNumberFormat extends NumberFormat {
return format(number, result, fieldPosition.getFieldDelegate(), false); return format(number, result, fieldPosition.getFieldDelegate(), false);
} }
private StringBuffer format(BigInteger number, StringBuffer result, private StringBuf format(BigInteger number, StringBuf result,
FieldDelegate delegate, boolean formatLong) { FieldDelegate delegate, boolean formatLong) {
boolean isNegative = number.signum() == -1; boolean isNegative = number.signum() == -1;
@ -936,7 +983,7 @@ public final class CompactNumberFormat extends NumberFormat {
* {@code NumberFormat.Field.SIGN} and * {@code NumberFormat.Field.SIGN} and
* {@code NumberFormat.Field.PREFIX} fields * {@code NumberFormat.Field.PREFIX} fields
*/ */
private void appendPrefix(StringBuffer result, String prefix, private void appendPrefix(StringBuf result, String prefix,
FieldDelegate delegate) { FieldDelegate delegate) {
append(result, expandAffix(prefix), delegate, append(result, expandAffix(prefix), delegate,
getFieldPositions(prefix, NumberFormat.Field.PREFIX)); getFieldPositions(prefix, NumberFormat.Field.PREFIX));
@ -952,7 +999,7 @@ public final class CompactNumberFormat extends NumberFormat {
* {@code NumberFormat.Field.SIGN} and * {@code NumberFormat.Field.SIGN} and
* {@code NumberFormat.Field.SUFFIX} fields * {@code NumberFormat.Field.SUFFIX} fields
*/ */
private void appendSuffix(StringBuffer result, String suffix, private void appendSuffix(StringBuf result, String suffix,
FieldDelegate delegate) { FieldDelegate delegate) {
append(result, expandAffix(suffix), delegate, append(result, expandAffix(suffix), delegate,
getFieldPositions(suffix, NumberFormat.Field.SUFFIX)); getFieldPositions(suffix, NumberFormat.Field.SUFFIX));
@ -968,7 +1015,7 @@ public final class CompactNumberFormat extends NumberFormat {
* @param positions a list of {@code FieldPosition} in the given * @param positions a list of {@code FieldPosition} in the given
* string * string
*/ */
private void append(StringBuffer result, String string, private void append(StringBuf result, String string,
FieldDelegate delegate, List<FieldPosition> positions) { FieldDelegate delegate, List<FieldPosition> positions) {
if (!string.isEmpty()) { if (!string.isEmpty()) {
int start = result.length(); int start = result.length();
@ -1134,7 +1181,7 @@ public final class CompactNumberFormat extends NumberFormat {
public AttributedCharacterIterator formatToCharacterIterator(Object obj) { public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
CharacterIteratorFieldDelegate delegate CharacterIteratorFieldDelegate delegate
= new CharacterIteratorFieldDelegate(); = new CharacterIteratorFieldDelegate();
StringBuffer sb = new StringBuffer(); StringBuf sb = StringBufFactory.of();
if (obj instanceof Double || obj instanceof Float) { if (obj instanceof Double || obj instanceof Float) {
format(((Number) obj).doubleValue(), sb, delegate); format(((Number) obj).doubleValue(), sb, delegate);

View File

@ -346,6 +346,19 @@ public abstract class DateFormat extends Format {
throw new IllegalArgumentException("Cannot format given Object as a Date"); throw new IllegalArgumentException("Cannot format given Object as a Date");
} }
@Override
final StringBuf format(Object obj, StringBuf toAppendTo,
FieldPosition fieldPosition) {
if (obj instanceof Date) {
return format((Date) obj, toAppendTo, fieldPosition);
} else if (obj instanceof Number) {
return format(new Date(((Number) obj).longValue()),
toAppendTo, fieldPosition);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Date");
}
}
/** /**
* Formats a {@link Date} into a date-time string. The formatted * Formats a {@link Date} into a date-time string. The formatted
* string is appended to the given {@code StringBuffer}. * string is appended to the given {@code StringBuffer}.
@ -371,6 +384,11 @@ public abstract class DateFormat extends Format {
public abstract StringBuffer format(Date date, StringBuffer toAppendTo, public abstract StringBuffer format(Date date, StringBuffer toAppendTo,
FieldPosition fieldPosition); FieldPosition fieldPosition);
StringBuf format(Date date, StringBuf toAppendTo,
FieldPosition fieldPosition) {
throw new UnsupportedOperationException("Subclasses should override this method");
}
/** /**
* Formats a {@link Date} into a date-time string. * Formats a {@link Date} into a date-time string.
* *
@ -379,9 +397,15 @@ public abstract class DateFormat extends Format {
*/ */
public final String format(Date date) public final String format(Date date)
{ {
if ("java.text".equals(getClass().getPackageName())
&& "java.text".equals(numberFormat.getClass().getPackageName())) {
return format(date, StringBufFactory.of(),
DontCareFieldPosition.INSTANCE).toString();
} else {
return format(date, new StringBuffer(), return format(date, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString(); DontCareFieldPosition.INSTANCE).toString();
} }
}
/** /**
* Parses text from the beginning of the given string to produce a date. * Parses text from the beginning of the given string to produce a date.

View File

@ -556,9 +556,9 @@ public class DecimalFormat extends NumberFormat {
((BigInteger)number).bitLength () < 64)) { ((BigInteger)number).bitLength () < 64)) {
return format(((Number)number).longValue(), toAppendTo, pos); return format(((Number)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigDecimal) { } else if (number instanceof BigDecimal) {
return format((BigDecimal)number, toAppendTo, pos); return format((BigDecimal)number, StringBufFactory.of(toAppendTo), pos).asStringBuffer();
} else if (number instanceof BigInteger) { } else if (number instanceof BigInteger) {
return format((BigInteger)number, toAppendTo, pos); return format((BigInteger)number, StringBufFactory.of(toAppendTo), pos).asStringBuffer();
} else if (number instanceof Number) { } else if (number instanceof Number) {
return format(((Number)number).doubleValue(), toAppendTo, pos); return format(((Number)number).doubleValue(), toAppendTo, pos);
} else { } else {
@ -566,6 +566,28 @@ public class DecimalFormat extends NumberFormat {
} }
} }
@Override
final StringBuf format(Object number,
StringBuf toAppendTo,
FieldPosition pos) {
if (number instanceof Long || number instanceof Integer ||
number instanceof Short || number instanceof Byte ||
number instanceof AtomicInteger ||
number instanceof AtomicLong ||
(number instanceof BigInteger &&
((BigInteger) number).bitLength() < 64)) {
return format(((Number) number).longValue(), toAppendTo, pos);
} else if (number instanceof BigDecimal) {
return format((BigDecimal) number, toAppendTo, pos);
} else if (number instanceof BigInteger) {
return format((BigInteger) number, toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number) number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
}
/** /**
* Formats a double to produce a string. * Formats a double to produce a string.
* @param number The double to format * @param number The double to format
@ -588,6 +610,12 @@ public class DecimalFormat extends NumberFormat {
@Override @Override
public StringBuffer format(double number, StringBuffer result, public StringBuffer format(double number, StringBuffer result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
return format(number, StringBufFactory.of(result), fieldPosition).asStringBuffer();
}
@Override
StringBuf format(double number, StringBuf result,
FieldPosition fieldPosition) {
// If fieldPosition is a DontCareFieldPosition instance we can // If fieldPosition is a DontCareFieldPosition instance we can
// try to go to fast-path code. // try to go to fast-path code.
boolean tryFastPath = false; boolean tryFastPath = false;
@ -619,7 +647,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string * @return The formatted number string
*/ */
StringBuffer format(double number, StringBuffer result, StringBuf format(double number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
boolean nanOrInfinity = handleNaN(number, result, delegate); boolean nanOrInfinity = handleNaN(number, result, delegate);
@ -666,7 +694,7 @@ public class DecimalFormat extends NumberFormat {
* @param delegate notified of locations of sub fields * @param delegate notified of locations of sub fields
* @return true, if number is a NaN; false otherwise * @return true, if number is a NaN; false otherwise
*/ */
boolean handleNaN(double number, StringBuffer result, boolean handleNaN(double number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
if (Double.isNaN(number) if (Double.isNaN(number)
|| (Double.isInfinite(number) && multiplier == 0)) { || (Double.isInfinite(number) && multiplier == 0)) {
@ -691,7 +719,7 @@ public class DecimalFormat extends NumberFormat {
* @return true, if number is a {@code Double.NEGATIVE_INFINITY} or * @return true, if number is a {@code Double.NEGATIVE_INFINITY} or
* {@code Double.POSITIVE_INFINITY}; false otherwise * {@code Double.POSITIVE_INFINITY}; false otherwise
*/ */
boolean handleInfinity(double number, StringBuffer result, boolean handleInfinity(double number, StringBuf result,
FieldDelegate delegate, boolean isNegative) { FieldDelegate delegate, boolean isNegative) {
if (Double.isInfinite(number)) { if (Double.isInfinite(number)) {
if (isNegative) { if (isNegative) {
@ -720,7 +748,7 @@ public class DecimalFormat extends NumberFormat {
return false; return false;
} }
StringBuffer doubleSubformat(double number, StringBuffer result, StringBuf doubleSubformat(double number, StringBuf result,
FieldDelegate delegate, boolean isNegative) { FieldDelegate delegate, boolean isNegative) {
synchronized (digitList) { synchronized (digitList) {
int maxIntDigits = super.getMaximumIntegerDigits(); int maxIntDigits = super.getMaximumIntegerDigits();
@ -761,6 +789,14 @@ public class DecimalFormat extends NumberFormat {
fieldPosition.setBeginIndex(0); fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0); fieldPosition.setEndIndex(0);
return format(number, StringBufFactory.of(result), fieldPosition.getFieldDelegate()).asStringBuffer();
}
StringBuf format(long number, StringBuf result,
FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0);
return format(number, result, fieldPosition.getFieldDelegate()); return format(number, result, fieldPosition.getFieldDelegate());
} }
@ -774,7 +810,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @see java.text.FieldPosition * @see java.text.FieldPosition
*/ */
StringBuffer format(long number, StringBuffer result, StringBuf format(long number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
boolean isNegative = (number < 0); boolean isNegative = (number < 0);
if (isNegative) { if (isNegative) {
@ -849,7 +885,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @see java.text.FieldPosition * @see java.text.FieldPosition
*/ */
private StringBuffer format(BigDecimal number, StringBuffer result, private StringBuf format(BigDecimal number, StringBuf result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0); fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0); fieldPosition.setEndIndex(0);
@ -865,7 +901,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @return The formatted number string * @return The formatted number string
*/ */
StringBuffer format(BigDecimal number, StringBuffer result, StringBuf format(BigDecimal number, StringBuf result,
FieldDelegate delegate) { FieldDelegate delegate) {
if (multiplier != 1) { if (multiplier != 1) {
number = number.multiply(getBigDecimalMultiplier()); number = number.multiply(getBigDecimalMultiplier());
@ -908,7 +944,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @see java.text.FieldPosition * @see java.text.FieldPosition
*/ */
private StringBuffer format(BigInteger number, StringBuffer result, private StringBuf format(BigInteger number, StringBuf result,
FieldPosition fieldPosition) { FieldPosition fieldPosition) {
fieldPosition.setBeginIndex(0); fieldPosition.setBeginIndex(0);
fieldPosition.setEndIndex(0); fieldPosition.setEndIndex(0);
@ -926,7 +962,7 @@ public class DecimalFormat extends NumberFormat {
* mode being set to RoundingMode.UNNECESSARY * mode being set to RoundingMode.UNNECESSARY
* @see java.text.FieldPosition * @see java.text.FieldPosition
*/ */
StringBuffer format(BigInteger number, StringBuffer result, StringBuf format(BigInteger number, StringBuf result,
FieldDelegate delegate, boolean formatLong) { FieldDelegate delegate, boolean formatLong) {
if (multiplier != 1) { if (multiplier != 1) {
number = number.multiply(getBigIntegerMultiplier()); number = number.multiply(getBigIntegerMultiplier());
@ -986,7 +1022,7 @@ public class DecimalFormat extends NumberFormat {
public AttributedCharacterIterator formatToCharacterIterator(Object obj) { public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
CharacterIteratorFieldDelegate delegate = CharacterIteratorFieldDelegate delegate =
new CharacterIteratorFieldDelegate(); new CharacterIteratorFieldDelegate();
StringBuffer sb = new StringBuffer(); StringBuf sb = StringBufFactory.of();
if (obj instanceof Double || obj instanceof Float) { if (obj instanceof Double || obj instanceof Float) {
format(((Number)obj).doubleValue(), sb, delegate); format(((Number)obj).doubleValue(), sb, delegate);
@ -1779,7 +1815,7 @@ public class DecimalFormat extends NumberFormat {
* Complete the formatting of a finite number. On entry, the digitList must * Complete the formatting of a finite number. On entry, the digitList must
* be filled in with the correct digits. * be filled in with the correct digits.
*/ */
private StringBuffer subformat(StringBuffer result, FieldDelegate delegate, private StringBuf subformat(StringBuf result, FieldDelegate delegate,
boolean isNegative, boolean isInteger, boolean isNegative, boolean isInteger,
int maxIntDigits, int minIntDigits, int maxIntDigits, int minIntDigits,
int maxFraDigits, int minFraDigits) { int maxFraDigits, int minFraDigits) {
@ -1821,7 +1857,7 @@ public class DecimalFormat extends NumberFormat {
* @param maxFraDigits maximum fraction digits * @param maxFraDigits maximum fraction digits
* @param minFraDigits minimum fraction digits * @param minFraDigits minimum fraction digits
*/ */
void subformatNumber(StringBuffer result, FieldDelegate delegate, void subformatNumber(StringBuf result, FieldDelegate delegate,
boolean isNegative, boolean isInteger, boolean isNegative, boolean isInteger,
int maxIntDigits, int minIntDigits, int maxIntDigits, int minIntDigits,
int maxFraDigits, int minFraDigits) { int maxFraDigits, int minFraDigits) {
@ -2108,7 +2144,7 @@ public class DecimalFormat extends NumberFormat {
* <p> * <p>
* This is used by {@code subformat} to add the prefix/suffix. * This is used by {@code subformat} to add the prefix/suffix.
*/ */
private void append(StringBuffer result, String string, private void append(StringBuf result, String string,
FieldDelegate delegate, FieldDelegate delegate,
FieldPosition[] positions, FieldPosition[] positions,
Format.Field signAttribute) { Format.Field signAttribute) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -36,10 +36,10 @@ class DontCareFieldPosition extends FieldPosition {
private final Format.FieldDelegate noDelegate = new Format.FieldDelegate() { private final Format.FieldDelegate noDelegate = new Format.FieldDelegate() {
public void formatted(Format.Field attr, Object value, int start, public void formatted(Format.Field attr, Object value, int start,
int end, StringBuffer buffer) { int end, Format.StringBuf buffer) {
} }
public void formatted(int fieldID, Format.Field attr, Object value, public void formatted(int fieldID, Format.Field attr, Object value,
int start, int end, StringBuffer buffer) { int start, int end, Format.StringBuf buffer) {
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -290,7 +290,7 @@ public class FieldPosition {
private boolean encounteredField; private boolean encounteredField;
public void formatted(Format.Field attr, Object value, int start, public void formatted(Format.Field attr, Object value, int start,
int end, StringBuffer buffer) { int end, Format.StringBuf buffer) {
if (!encounteredField && matchesField(attr)) { if (!encounteredField && matchesField(attr)) {
setBeginIndex(start); setBeginIndex(start);
setEndIndex(end); setEndIndex(end);
@ -299,7 +299,7 @@ public class FieldPosition {
} }
public void formatted(int fieldID, Format.Field attr, Object value, public void formatted(int fieldID, Format.Field attr, Object value,
int start, int end, StringBuffer buffer) { int start, int end, Format.StringBuf buffer) {
if (!encounteredField && matchesField(attr, fieldID)) { if (!encounteredField && matchesField(attr, fieldID)) {
setBeginIndex(start); setBeginIndex(start);
setEndIndex(end); setEndIndex(end);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -148,7 +148,8 @@ public abstract class Format implements Serializable, Cloneable {
} }
/** /**
* Formats an object to produce a string. This is equivalent to * Formats an object to produce a string.
* This method returns a string that would be equal to the string returned by
* <blockquote> * <blockquote>
* {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj, * {@link #format(Object, StringBuffer, FieldPosition) format}<code>(obj,
* new StringBuffer(), new FieldPosition(0)).toString();</code> * new StringBuffer(), new FieldPosition(0)).toString();</code>
@ -160,8 +161,12 @@ public abstract class Format implements Serializable, Cloneable {
* object * object
*/ */
public final String format (Object obj) { public final String format (Object obj) {
if ("java.text".equals(getClass().getPackageName())) {
return format(obj, StringBufFactory.of(), new FieldPosition(0)).toString();
} else {
return format(obj, new StringBuffer(), new FieldPosition(0)).toString(); return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
} }
}
/** /**
* Formats an object and appends the resulting text to a given string * Formats an object and appends the resulting text to a given string
@ -185,6 +190,12 @@ public abstract class Format implements Serializable, Cloneable {
StringBuffer toAppendTo, StringBuffer toAppendTo,
FieldPosition pos); FieldPosition pos);
StringBuf format(Object obj,
StringBuf toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("Subclasses should override this method");
}
/** /**
* Formats an Object producing an {@code AttributedCharacterIterator}. * Formats an Object producing an {@code AttributedCharacterIterator}.
* You can use the returned {@code AttributedCharacterIterator} * You can use the returned {@code AttributedCharacterIterator}
@ -394,7 +405,7 @@ public abstract class Format implements Serializable, Cloneable {
* NOT modify it. * NOT modify it.
*/ */
public void formatted(Format.Field attr, Object value, int start, public void formatted(Format.Field attr, Object value, int start,
int end, StringBuffer buffer); int end, StringBuf buffer);
/** /**
* Notified when a particular region of the String is formatted. * Notified when a particular region of the String is formatted.
@ -408,6 +419,38 @@ public abstract class Format implements Serializable, Cloneable {
* NOT modify it. * NOT modify it.
*/ */
public void formatted(int fieldID, Format.Field attr, Object value, public void formatted(int fieldID, Format.Field attr, Object value,
int start, int end, StringBuffer buffer); int start, int end, StringBuf buffer);
}
/**
* StringBuf is the minimal common interface of {@code StringBuffer} and {@code StringBuilder}.
* It is used by the various {@code Format} implementations as the internal string buffer.
*/
sealed interface StringBuf
permits StringBufFactory.StringBufferImpl, StringBufFactory.StringBuilderImpl {
int length();
String substring(int start, int end);
String substring(int start);
StringBuf append(char c);
StringBuf append(String str);
StringBuf append(int i);
StringBuf append(char[] str, int offset, int len);
StringBuf append(CharSequence s, int start, int end);
StringBuf append(StringBuffer sb);
boolean isProxyStringBuilder();
StringBuffer asStringBuffer();
StringBuilder asStringBuilder();
} }
} }

View File

@ -356,7 +356,7 @@ public final class ListFormat extends Format {
public String format(List<String> input) { public String format(List<String> input) {
Objects.requireNonNull(input); Objects.requireNonNull(input);
return format(input, new StringBuffer(), return format(input, StringBufFactory.of(),
DontCareFieldPosition.INSTANCE).toString(); DontCareFieldPosition.INSTANCE).toString();
} }
@ -381,6 +381,18 @@ public final class ListFormat extends Format {
Objects.requireNonNull(obj); Objects.requireNonNull(obj);
Objects.requireNonNull(toAppendTo); Objects.requireNonNull(toAppendTo);
return format(obj, StringBufFactory.of(toAppendTo)).asStringBuffer();
}
@Override
StringBuf format(Object obj, StringBuf toAppendTo, FieldPosition pos) {
Objects.requireNonNull(obj);
Objects.requireNonNull(toAppendTo);
return format(obj, toAppendTo);
}
private StringBuf format(Object obj, StringBuf toAppendTo) {
if (obj instanceof Object[] objs) { if (obj instanceof Object[] objs) {
return generateMessageFormat(objs).format(objs, toAppendTo, DontCareFieldPosition.INSTANCE); return generateMessageFormat(objs).format(objs, toAppendTo, DontCareFieldPosition.INSTANCE);
} else if (obj instanceof List<?> objs) { } else if (obj instanceof List<?> objs) {

View File

@ -1027,12 +1027,13 @@ public class MessageFormat extends Format {
public final StringBuffer format(Object[] arguments, StringBuffer result, public final StringBuffer format(Object[] arguments, StringBuffer result,
FieldPosition pos) FieldPosition pos)
{ {
return subformat(arguments, result, pos, null); return subformat(arguments, StringBufFactory.of(result), pos, null).asStringBuffer();
} }
/** /**
* Creates a MessageFormat with the given pattern and uses it * Creates a MessageFormat with the given pattern and uses it
* to format the given arguments. This is equivalent to * to format the given arguments.
* This method returns a string that would be equal to the string returned by
* <blockquote> * <blockquote>
* <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code> * <code>(new {@link #MessageFormat(String) MessageFormat}(pattern)).{@link #format(java.lang.Object[], java.lang.StringBuffer, java.text.FieldPosition) format}(arguments, new StringBuffer(), null).toString()</code>
* </blockquote> * </blockquote>
@ -1076,6 +1077,12 @@ public class MessageFormat extends Format {
public final StringBuffer format(Object arguments, StringBuffer result, public final StringBuffer format(Object arguments, StringBuffer result,
FieldPosition pos) FieldPosition pos)
{ {
return subformat((Object[]) arguments, StringBufFactory.of(result), pos, null).asStringBuffer();
}
@Override
final StringBuf format(Object arguments, StringBuf result,
FieldPosition pos) {
return subformat((Object[]) arguments, result, pos, null); return subformat((Object[]) arguments, result, pos, null);
} }
@ -1116,7 +1123,7 @@ public class MessageFormat extends Format {
*/ */
public AttributedCharacterIterator formatToCharacterIterator(Object arguments) { public AttributedCharacterIterator formatToCharacterIterator(Object arguments) {
Objects.requireNonNull(arguments, "arguments must not be null"); Objects.requireNonNull(arguments, "arguments must not be null");
StringBuffer result = new StringBuffer(); StringBuf result = StringBufFactory.of();
ArrayList<AttributedCharacterIterator> iterators = new ArrayList<>(); ArrayList<AttributedCharacterIterator> iterators = new ArrayList<>();
subformat((Object[]) arguments, result, null, iterators); subformat((Object[]) arguments, result, null, iterators);
@ -1472,7 +1479,7 @@ public class MessageFormat extends Format {
* {@code arguments} array is not of the type * {@code arguments} array is not of the type
* expected by the format element(s) that use it. * expected by the format element(s) that use it.
*/ */
private StringBuffer subformat(Object[] arguments, StringBuffer result, private StringBuf subformat(Object[] arguments, StringBuf result,
FieldPosition fp, List<AttributedCharacterIterator> characterIterators) { FieldPosition fp, List<AttributedCharacterIterator> characterIterators) {
// note: this implementation assumes a fast substring & index. // note: this implementation assumes a fast substring & index.
// if this is not true, would be better to append chars one by one. // if this is not true, would be better to append chars one by one.
@ -1582,9 +1589,9 @@ public class MessageFormat extends Format {
/** /**
* Convenience method to append all the characters in * Convenience method to append all the characters in
* {@code iterator} to the StringBuffer {@code result}. * {@code iterator} to the StringBuf {@code result}.
*/ */
private void append(StringBuffer result, CharacterIterator iterator) { private void append(StringBuf result, CharacterIterator iterator) {
if (iterator.first() != CharacterIterator.DONE) { if (iterator.first() != CharacterIterator.DONE) {
char aChar; char aChar;

View File

@ -315,6 +315,23 @@ public abstract class NumberFormat extends Format {
} }
} }
@Override
StringBuf format(Object number,
StringBuf toAppendTo,
FieldPosition pos) {
if (number instanceof Long || number instanceof Integer ||
number instanceof Short || number instanceof Byte ||
number instanceof AtomicInteger || number instanceof AtomicLong ||
(number instanceof BigInteger &&
((BigInteger) number).bitLength() < 64)) {
return format(((Number) number).longValue(), toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number) number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
}
/** /**
* {@inheritDoc Format} * {@inheritDoc Format}
* *
@ -347,9 +364,14 @@ public abstract class NumberFormat extends Format {
if (result != null) if (result != null)
return result; return result;
if ("java.text".equals(getClass().getPackageName())) {
return format(number, StringBufFactory.of(),
DontCareFieldPosition.INSTANCE).toString();
} else {
return format(number, new StringBuffer(), return format(number, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString(); DontCareFieldPosition.INSTANCE).toString();
} }
}
/* /*
* fastFormat() is supposed to be implemented in concrete subclasses only. * fastFormat() is supposed to be implemented in concrete subclasses only.
@ -367,9 +389,14 @@ public abstract class NumberFormat extends Format {
* @see java.text.Format#format * @see java.text.Format#format
*/ */
public final String format(long number) { public final String format(long number) {
if ("java.text".equals(getClass().getPackageName())) {
return format(number, StringBufFactory.of(),
DontCareFieldPosition.INSTANCE).toString();
} else {
return format(number, new StringBuffer(), return format(number, new StringBuffer(),
DontCareFieldPosition.INSTANCE).toString(); DontCareFieldPosition.INSTANCE).toString();
} }
}
/** /**
* Specialization of format. * Specialization of format.
@ -394,6 +421,12 @@ public abstract class NumberFormat extends Format {
StringBuffer toAppendTo, StringBuffer toAppendTo,
FieldPosition pos); FieldPosition pos);
StringBuf format(double number,
StringBuf toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("Subclasses should override this method");
}
/** /**
* Specialization of format. * Specialization of format.
* *
@ -417,6 +450,12 @@ public abstract class NumberFormat extends Format {
StringBuffer toAppendTo, StringBuffer toAppendTo,
FieldPosition pos); FieldPosition pos);
StringBuf format(long number,
StringBuf toAppendTo,
FieldPosition pos) {
throw new UnsupportedOperationException("Subclasses should override this method");
}
/** /**
* Parses text from the beginning of the given string to produce a {@code Number}. * Parses text from the beginning of the given string to produce a {@code Number}.
* <p> * <p>

View File

@ -968,11 +968,18 @@ public class SimpleDateFormat extends DateFormat {
FieldPosition pos) FieldPosition pos)
{ {
pos.beginIndex = pos.endIndex = 0; pos.beginIndex = pos.endIndex = 0;
return format(date, StringBufFactory.of(toAppendTo), pos.getFieldDelegate()).asStringBuffer();
}
@Override
final StringBuf format(Date date, StringBuf toAppendTo,
FieldPosition pos) {
pos.beginIndex = pos.endIndex = 0;
return format(date, toAppendTo, pos.getFieldDelegate()); return format(date, toAppendTo, pos.getFieldDelegate());
} }
// Called from Format after creating a FieldDelegate // Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo, private StringBuf format(Date date, StringBuf toAppendTo,
FieldDelegate delegate) { FieldDelegate delegate) {
// Convert input date to time field list // Convert input date to time field list
calendar.setTime(date); calendar.setTime(date);
@ -1024,7 +1031,7 @@ public class SimpleDateFormat extends DateFormat {
*/ */
@Override @Override
public AttributedCharacterIterator formatToCharacterIterator(Object obj) { public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
StringBuffer sb = new StringBuffer(); StringBuf sb = StringBufFactory.of();
CharacterIteratorFieldDelegate delegate = new CharacterIteratorFieldDelegate delegate = new
CharacterIteratorFieldDelegate(); CharacterIteratorFieldDelegate();
@ -1130,7 +1137,7 @@ public class SimpleDateFormat extends DateFormat {
* Private member function that does the real date/time formatting. * Private member function that does the real date/time formatting.
*/ */
private void subFormat(int patternCharIndex, int count, private void subFormat(int patternCharIndex, int count,
FieldDelegate delegate, StringBuffer buffer, FieldDelegate delegate, StringBuf buffer,
boolean useDateFormatSymbols) boolean useDateFormatSymbols)
{ {
int maxIntCount = Integer.MAX_VALUE; int maxIntCount = Integer.MAX_VALUE;
@ -1320,7 +1327,11 @@ public class SimpleDateFormat extends DateFormat {
} }
int num = (value / 60) * 100 + (value % 60); int num = (value / 60) * 100 + (value % 60);
CalendarUtils.sprintf0d(buffer, num, width); if (buffer.isProxyStringBuilder()) {
CalendarUtils.sprintf0d(buffer.asStringBuilder(), num, width);
} else {
CalendarUtils.sprintf0d(buffer.asStringBuffer(), num, width);
}
break; break;
case PATTERN_ISO_ZONE: // 'X' case PATTERN_ISO_ZONE: // 'X'
@ -1340,7 +1351,11 @@ public class SimpleDateFormat extends DateFormat {
value = -value; value = -value;
} }
CalendarUtils.sprintf0d(buffer, value / 60, 2); if (buffer.isProxyStringBuilder()) {
CalendarUtils.sprintf0d(buffer.asStringBuilder(), value / 60, 2);
} else {
CalendarUtils.sprintf0d(buffer.asStringBuffer(), value / 60, 2);
}
if (count == 1) { if (count == 1) {
break; break;
} }
@ -1348,7 +1363,11 @@ public class SimpleDateFormat extends DateFormat {
if (count == 3) { if (count == 3) {
buffer.append(':'); buffer.append(':');
} }
CalendarUtils.sprintf0d(buffer, value % 60, 2); if (buffer.isProxyStringBuilder()) {
CalendarUtils.sprintf0d(buffer.asStringBuilder(), value % 60, 2);
} else {
CalendarUtils.sprintf0d(buffer.asStringBuffer(), value % 60, 2);
}
break; break;
default: default:
@ -1382,7 +1401,7 @@ public class SimpleDateFormat extends DateFormat {
/** /**
* Formats a number with the specified minimum and maximum number of digits. * Formats a number with the specified minimum and maximum number of digits.
*/ */
private void zeroPaddingNumber(int value, int minDigits, int maxDigits, StringBuffer buffer) private void zeroPaddingNumber(int value, int minDigits, int maxDigits, StringBuf buffer)
{ {
// Optimization for 1, 2 and 4 digit numbers. This should // Optimization for 1, 2 and 4 digit numbers. This should
// cover most cases of formatting date/time related items. // cover most cases of formatting date/time related items.
@ -1425,7 +1444,17 @@ public class SimpleDateFormat extends DateFormat {
numberFormat.setMinimumIntegerDigits(minDigits); numberFormat.setMinimumIntegerDigits(minDigits);
numberFormat.setMaximumIntegerDigits(maxDigits); numberFormat.setMaximumIntegerDigits(maxDigits);
numberFormat.format((long)value, buffer, DontCareFieldPosition.INSTANCE); if (buffer.isProxyStringBuilder()) {
//User can set numberFormat with a user-defined NumberFormat which
//not override format(long, StringBuf, FieldPosition).
if ("java.text".equals(numberFormat.getClass().getPackageName())) {
numberFormat.format((long) value, buffer, DontCareFieldPosition.INSTANCE);
} else {
buffer.append(numberFormat.format((long) value, new StringBuffer(), DontCareFieldPosition.INSTANCE));
}
} else {
numberFormat.format((long) value, buffer.asStringBuffer(), DontCareFieldPosition.INSTANCE);
}
} }
@ -2565,5 +2594,4 @@ public class SimpleDateFormat extends DateFormat {
originalNumberFormat = numberFormat; originalNumberFormat = numberFormat;
} }
} }
} }

View File

@ -0,0 +1,216 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.text;
import java.text.Format.StringBuf;
/**
* {@code StringBufFactory} creates implementations of {@code Format.StringBuf},
* which is an interface with the minimum overlap required to support {@code StringBuffer}
* and {@code StringBuilder} in {@code Format}. This allows for {@code StringBuilder} to be used
* in place of {@code StringBuffer} to provide performance benefits for JDK internal
* {@code Format} subclasses.
*/
final class StringBufFactory {
private StringBufFactory() {
}
static StringBuf of(StringBuffer sb) {
return new StringBufferImpl(sb);
}
static StringBuf of(StringBuilder sb) {
return new StringBuilderImpl(sb);
}
static StringBuf of() {
return new StringBuilderImpl();
}
final static class StringBufferImpl implements StringBuf {
private final StringBuffer sb;
StringBufferImpl(StringBuffer sb) {
this.sb = sb;
}
@Override
public int length() {
return sb.length();
}
@Override
public String substring(int start, int end) {
return sb.substring(start, end);
}
@Override
public String substring(int start) {
return sb.substring(start);
}
@Override
public StringBuf append(char c) {
sb.append(c);
return this;
}
@Override
public StringBuf append(String str) {
sb.append(str);
return this;
}
@Override
public StringBuf append(int i) {
sb.append(i);
return this;
}
@Override
public StringBuf append(char[] str, int offset, int len) {
sb.append(str, offset, len);
return this;
}
@Override
public StringBuf append(CharSequence s, int start, int end) {
sb.append(s, start, end);
return this;
}
@Override
public StringBuf append(StringBuffer asb) {
sb.append(asb);
return this;
}
@Override
public boolean isProxyStringBuilder() {
return false;
}
@Override
public StringBuffer asStringBuffer() {
return sb;
}
@Override
public StringBuilder asStringBuilder() {
throw new AssertionError("Can't cast StringBuffer to StringBuilder");
}
@Override
public String toString() {
return sb.toString();
}
}
final static class StringBuilderImpl implements StringBuf {
private final StringBuilder sb;
StringBuilderImpl(StringBuilder sb) {
this.sb = sb;
}
StringBuilderImpl() {
this.sb = new StringBuilder();
}
@Override
public int length() {
return sb.length();
}
@Override
public String substring(int start, int end) {
return sb.substring(start, end);
}
@Override
public String substring(int start) {
return sb.substring(start);
}
@Override
public StringBuf append(char c) {
sb.append(c);
return this;
}
@Override
public StringBuf append(String str) {
sb.append(str);
return this;
}
@Override
public StringBuf append(int i) {
sb.append(i);
return this;
}
@Override
public StringBuf append(char[] str, int offset, int len) {
sb.append(str, offset, len);
return this;
}
@Override
public StringBuf append(CharSequence s, int start, int end) {
sb.append(s, start, end);
return this;
}
@Override
public StringBuf append(StringBuffer asb) {
sb.append(asb);
return this;
}
@Override
public boolean isProxyStringBuilder() {
return true;
}
@Override
public StringBuffer asStringBuffer() {
throw new AssertionError("Can't cast StringBuilder to StringBuffer");
}
@Override
public StringBuilder asStringBuilder() {
return sb;
}
@Override
public String toString() {
return sb.toString();
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.text;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
@State(Scope.Benchmark)
public class DateFormatterBench {
private Date date;
private Object objDate;
@Setup
public void setup() {
date = new Date();
objDate = new Date();
}
private DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.FULL, Locale.ENGLISH);
@Benchmark
public String testFormatDate() {
return dateFormat.format(date);
}
@Benchmark
public String testFormatObject() {
return dateFormat.format(objDate);
}
public static void main(String... args) throws Exception {
Options opts = new OptionsBuilder().include(DateFormatterBench.class.getSimpleName()).shouldDoGC(true).build();
new Runner(opts).run();
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.text;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.text.ListFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
@State(Scope.Benchmark)
public class ListFormatterBench {
private List<String> data;
@Setup
public void setup() {
data = List.of("foo", "bar", "baz", "qux", "quux", "quuz");
}
private ListFormat listFormat = ListFormat.getInstance();
@Benchmark
public String testListFormat() {
return listFormat.format(data);
}
public static void main(String... args) throws Exception {
Options opts = new OptionsBuilder().include(ListFormatterBench.class.getSimpleName()).shouldDoGC(true).build();
new Runner(opts).run();
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.text;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
@State(Scope.Benchmark)
public class MessageFormatterBench {
private Object[][] values;
@Setup
public void setup() {
values = new Object[][]{
new Object[]{Integer.valueOf(13), "MyDisk1"},
new Object[]{Float.valueOf(25.6f), "MyDisk2"},
new Object[]{Double.valueOf(123.89), "MyDisk3"},
new Object[]{Long.valueOf(1234567), "MyDisk4"},
};
}
private MessageFormat messageFormat = new MessageFormat("There is {0} GB of free space on the {1}.", Locale.ENGLISH);
@Benchmark
@OperationsPerInvocation(4)
public void testMessageFormat(final Blackhole bh) {
for (Object[] value : values) {
bh.consume(messageFormat.format(value));
}
}
public static void main(String... args) throws Exception {
Options opts = new OptionsBuilder().include(MessageFormatterBench.class.getSimpleName()).shouldDoGC(true).build();
new Runner(opts).run();
}
}