<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
I think this goes against the grain: StringBuilder is a simple builder for non-localized unformatted output. For formatted output there’s Formatter, String.format and, with JEP 430[1], FMT.”…” to help output string data in more advanced, formatted and localized
 ways. The latter has traditionally lacked a bit in raw throughput, and String templates is a deep-cut approach to try and improve both the programming model and the performance characteristics.
<div><br>
</div>
<div>Let’s compare a few existing APIs (JDK 22 ea, —enable-preview enabled for the FMT.”…” micro:<br>
<div><br>
</div>
<div>
<pre style="background-color: rgb(43, 43, 43); color: rgb(169, 183, 198); font-family: "JetBrains Mono", monospace;"><pre style="font-family: "JetBrains Mono", monospace;">@Benchmark<br><span style="color: rgb(204, 120, 50);">public </span>String <span style="color: rgb(255, 198, 109);">toStringAppendHex8</span>() {<br>    StringBuilder result = <span style="color: rgb(204, 120, 50);">new </span>StringBuilder()<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">2048</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">31337</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">0xbeefcace</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">9000</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">4711</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">1337</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">2100</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>result.append(Integer.<span style="font-style: italic;">toHexString</span>(<span style="color: rgb(104, 151, 187);">2600</span>))<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    return </span>result.toString()<span style="color: rgb(204, 120, 50);">;<br></span>}<br><br>@Benchmark<br><span style="color: rgb(204, 120, 50);">public </span>String <span style="color: rgb(255, 198, 109);">toStringFMTHex8</span>() {<br>    <span style="color: rgb(204, 120, 50);">int </span>h1 = <span style="color: rgb(104, 151, 187);">2048</span><span style="color: rgb(204, 120, 50);">, </span>h2 = <span style="color: rgb(104, 151, 187);">31337</span><span style="color: rgb(204, 120, 50);">, </span>h3 = <span style="color: rgb(104, 151, 187);">0xbeefcace</span><span style="color: rgb(204, 120, 50);">, </span>h4 = <span style="color: rgb(104, 151, 187);">9000</span><span style="color: rgb(204, 120, 50);">, </span>h5 = <span style="color: rgb(104, 151, 187);">4711</span><span style="color: rgb(204, 120, 50);">, </span>h6 = <span style="color: rgb(104, 151, 187);">1337</span><span style="color: rgb(204, 120, 50);">, </span>h7 = <span style="color: rgb(104, 151, 187);">2100</span><span style="color: rgb(204, 120, 50);">, </span>h8 = <span style="color: rgb(104, 151, 187);">2600</span><span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    return </span><span style="color: rgb(152, 118, 170); font-style: italic;">FMT</span>.<span style="color: rgb(106, 135, 89);">"%x\{h1}%x\{h2}%x\{h3}%x\{h4}%x\{h5}%x\{h6}%x\{h7}%x\{h8}"</span><span style="color: rgb(204, 120, 50);">;<br></span>}<br><br>@Benchmark<br><span style="color: rgb(204, 120, 50);">public </span>String <span style="color: rgb(255, 198, 109);">toStringFormatHex8</span>() {<br>    StringBuilder result = <span style="color: rgb(204, 120, 50);">new </span>StringBuilder()<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>Formatter f = <span style="color: rgb(204, 120, 50);">new </span>Formatter(result)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2048</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">31337</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">0xbeefcace</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">9000</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">4711</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">1337</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2100</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    </span>f.format(<span style="color: rgb(106, 135, 89);">"%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2600</span>)<span style="color: rgb(204, 120, 50);">;<br></span><span style="color: rgb(204, 120, 50);">    return </span>result.toString()<span style="color: rgb(204, 120, 50);">;<br></span>}<br><br>@Benchmark<br><span style="color: rgb(204, 120, 50);">public </span>String <span style="color: rgb(255, 198, 109);">toStringFormatCombinedHex8</span>() {<br>    <span style="color: rgb(204, 120, 50);">return </span>String.<span style="font-style: italic;">format</span>(<span style="color: rgb(106, 135, 89);">"%x%x%x%x%x%x%x%x"</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2048</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">31337</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">0xbeefcace</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">9000</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">4711</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">1337</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2100</span><span style="color: rgb(204, 120, 50);">, </span><span style="color: rgb(104, 151, 187);">2600</span>)<span style="color: rgb(204, 120, 50);">;<br></span>}</pre></pre>
</div>
<div> </div>
<div>
<div><font face="Courier New">Benchmark                                  Mode  Cnt    Score   Error  Units</font></div>
<div><font face="Courier New">StringBuilders.toStringAppendHex8          avgt   15   19,521 ± 0,608  ns/op</font></div>
<div><font face="Courier New">StringBuilders.toStringFMTHex8             avgt   15   10,958 ± 0,838  ns/op</font></div>
<div><font face="Courier New">StringBuilders.toStringFormatHex8          avgt   15  378,327 ± 9,302  ns/op</font></div>
<div><font face="Courier New">StringBuilders.toStringFormatCombinedHex8  avgt   15  235,609 ± 6,315  ns/op</font></div>
</div>
<div><br>
</div>
<div>As we can see FMT.”%x…” is already a great deal faster here, while String.format and Formatter leave something to be desired.</div>
<div><br>
</div>
<div>One thing missing with the FMT approach is a natural way to format into pre-existing StringBuilder/Appendable (like the toStringFormatHex8 benchmark models). I think adding that would be a way more interesting development than to add more formatting methods
 to StringBuilder.</div>
<div><br>
</div>
<div>/Claes</div>
<div><br>
</div>
<div>[1] https://openjdk.org/jeps/430</div>
<div>
<div><br>
<blockquote type="cite">
<div>30 sep. 2023 kl. 14:06 skrev 温绍锦(高铁) <shaojin.wensj@alibaba-inc.com>:</div>
<br class="Apple-interchange-newline">
<div>
<div class="__aliyun_email_body_block">
<div style="line-height:1.7;font-family:Tahoma,Arial,STHeiti,SimSun;font-size:14.0px;color:#0070c0;">
<div style="clear:both;">There are many combinations of `append(Integer.toHexString(i))` and `append(Long.toHexString(i))` in the JDK code. I request to add method `appendHex(int)` and `appendHex(int)` to StringBuilder and StringBuffer. This can reduce duplicate
 code within the JDK and will also be useful to users.<br>
</div>
<div style="line-height:20.0px;clear:both;">
<div style="clear:both;"><br>
</div>
<div style="clear:both;">I submitted a PR ( <a href="https://github.com/openjdk/jdk/pull/15998" target="_blank">
https://github.com/openjdk/jdk/pull/15998</a> ), including the code and tests for the new method. I also replaced the code that uses the append + toHexString combination inside the JDK with appendHex.</div>
<span>
<div style="line-height:20.0px;clear:both;"><span><br>
</span></div>
Please review and don't hesitate to critique my approach and patch.</span></div>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</body>
</html>