I was creating a demo to demonstrate how much faster StringBuilder is than String concatenation.
I also wanted to demonstrate that String concatenation is the equivalent to making a new StringBuilder for each append. I wanted to demonstrate this with the following 2 blocks:
Simply concatenate a String
String result = "";
for (int i = 0; i < 200000; i++) {
    result += String.valueOf(i);
}
Create a new StringBuilder for each concatenation
String result = "";
for (int i = 0; i < 200000; i++) {
    result = new StringBuilder(result).append(String.valueOf(i)).toString();
}
My understanding was that the String concatenation example compiled to the same thing as creating a new StringBuilder for each concatenation. I even decompiled the code to see the same result for both (I know decompiled code is not necessarily an exact representation of the written or compiled code).
Obviously using a single StringBuilder for all appending ran in a fraction of the time of these 2 examples. But the weird thing is that the 2nd example (creating a new StringBuilder manually each time) ran at nearly half the time of simple concatenation example. Why is creating a new StringBuilder each time so much faster than concatenation?
(Using Java Adoptium Temurin 17 in case it matters)
Update For those asking for full code-
import java.util.Date;
public class App {
    public static void main(String[] args) {
        String result = "";
        Date start = new Date();
        for (int i = 0; i < 200000; i++) {
            result = new StringBuilder(result).append(String.valueOf(i)).toString();
            //result += String.valueOf(i);
        }
        Date end = new Date();
       System.out.println(end.getTime() - start.getTime());
    }
}
Like I said, it's a simple example. You can obviously just comment out the StringBuilder line and uncomment the concat line to test the other example.
As I mentioned below, I know Date is not meant to be used for metrics like this but it's a relatively simple example, and even without it, the difference is significantly noticeable in person.
I've tried this on 3 different Java Runtimes (Oracle 8, AdoptOpenJDK 11, and Adoptium Temurin 17), and while each one takes different amounts of time, the difference between the 2 is still pretty similar.
 
    