StringBuilder add a method append(int i, int width, char pad)

温绍锦(高铁) shaojin.wensj at alibaba-inc.com
Sat Sep 30 21:37:09 UTC 2023


I suggest that StringBuilder and StringBuffer add a method append(int i, int width, char pad),
StringBuilder add method append(int i, int width, char pad). As follows:
```java
public abstract class AbstractBuilder {
 public AbstractStringBuilder append(int i, int width, char pad) {
 // ...
 }
}
```
Such functionality is needed in many places in the JDK. In the JDK date processing code, there are many places where StringBuilder.append(int) is used to specify the width. 
For example, in CalendarUtils, it is like this:
```java
package sun.util.calendar;
public final class CalendarUtils {
 /**
 * Mimics sprintf(buf, "%0*d", decaimal, width).
 */
 public static StringBuilder sprintf0d(StringBuilder sb, int value, int width) {
 long d = value;
 if (d < 0) {
 sb.append('-');
 d = -d;
 --width;
 }
 int n = 10;
 for (int i = 2; i < width; i++) {
 n *= 10;
 }
 for (int i = 1; i < width && d < n; i++) {
 sb.append('0');
 n /= 10;
 }
 sb.append(d);
 return sb;
 }
 public static StringBuffer sprintf0d(StringBuffer sb, int value, int width) {
 long d = value;
 if (d < 0) {
 sb.append('-');
 d = -d;
 --width;
 }
 int n = 10;
 for (int i = 2; i < width; i++) {
 n *= 10;
 }
 for (int i = 1; i < width && d < n; i++) {
 sb.append('0');
 n /= 10;
 }
 sb.append(d);
 return sb;
 }
}
```
This is the case in LocalTime. To fill in '0', first add 1000 or 1000_000 or 1000_000_000, and then do substring(1) processing after append. Such code has poor readability and poor performance.
```java
package java.time;
public final class LocalTime {
 public String toString() {
 StringBuilder buf = new StringBuilder(18);
 int hourValue = hour;
 int minuteValue = minute;
 int secondValue = second;
 int nanoValue = nano;
 buf.append(hourValue < 10 ? "0" : "").append(hourValue)
 .append(minuteValue < 10 ? ":0" : ":").append(minuteValue);
 if (secondValue > 0 || nanoValue > 0) {
 buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
 if (nanoValue > 0) {
 buf.append('.');
 if (nanoValue % 1000_000 == 0) {
 buf.append(Integer.toString((nanoValue / 1000_000) + 1000).substring(1));
 } else if (nanoValue % 1000 == 0) {
 buf.append(Integer.toString((nanoValue / 1000) + 1000_000).substring(1));
 } else {
 buf.append(Integer.toString((nanoValue) + 1000_000_000).substring(1));
 }
 }
 }
 return buf.toString();
 }
}
```
I submitted a PR ( https://github.com/openjdk/jdk/pull/15993 <https://github.com/openjdk/jdk/pull/15993 > ), including the code and tests for the new method. Please review and don't hesitate to critique my approach and patch.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/core-libs-dev/attachments/20231001/cb224357/attachment.htm>


More information about the core-libs-dev mailing list