> Yes, StringJoiner is really good at joining Strings (hence the name).
> But it is not very good at joining primitives. Because you have to
> convert each primitive to a String before you can add it.
> StringBuilder does not need to allocate a String when you add a
> primitive.

I've reworked my patch to affect only the spots where we either already have 
Strings 
or do convertion to String (just like StringBuilder.append(Object) does using 
String::valueOf).

Also I've dropped erroneous changes to Atomic*Array (thanks Martin for spotting 
this).

Regards,
Sergey Tsypanov
diff --git a/src/java.base/share/classes/java/util/Arrays.java b/src/java.base/share/classes/java/util/Arrays.java
--- a/src/java.base/share/classes/java/util/Arrays.java
+++ b/src/java.base/share/classes/java/util/Arrays.java
@@ -5123,19 +5123,14 @@
     public static String toString(Object[] a) {
         if (a == null)
             return "null";
-
-        int iMax = a.length - 1;
-        if (iMax == -1)
+        if (a.length == 0)
             return "[]";
 
-        StringBuilder b = new StringBuilder();
-        b.append('[');
-        for (int i = 0; ; i++) {
-            b.append(String.valueOf(a[i]));
-            if (i == iMax)
-                return b.append(']').toString();
-            b.append(", ");
+        StringJoiner sj = new StringJoiner(", ", "[", "]");
+        for (Object o : a) {
+            sj.add(String.valueOf(o));
         }
+        return sj.toString();
     }
 
     /**
diff --git a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java
--- a/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java
+++ b/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java
@@ -309,12 +309,10 @@
      * of an annotation.
      */
     private static String toSourceString(String s) {
-        StringBuilder sb = new StringBuilder();
-        sb.append('"');
+        StringJoiner sb = new StringJoiner("", "\"", "\"");
         for (int i = 0; i < s.length(); i++) {
-            sb.append(quote(s.charAt(i)));
+            sb.add(quote(s.charAt(i)));
         }
-        sb.append('"');
         return sb.toString();
     }
 
diff --git a/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java b/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java
--- a/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java
+++ b/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java
@@ -26,10 +26,9 @@
 package sun.security.pkcs;
 
 import java.io.IOException;
-import java.util.ArrayList;
+import java.util.StringJoiner;
 
 import sun.security.util.HexDumpEncoder;
-import sun.security.util.DerInputStream;
 import sun.security.util.DerValue;
 import sun.security.x509.GeneralNames;
 import sun.security.x509.SerialNumber;
@@ -92,14 +91,10 @@
     }
 
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        sb.append("[\n");
-        for (int i = 0; i < certId.length; i++) {
-            sb.append(certId[i].toString());
+        StringJoiner sb = new StringJoiner("", "[\n", "\n]");
+        for (ESSCertId id : certId) {
+            sb.add(id.toString());
         }
-        // format policies as a string
-        sb.append("\n]");
-
         return sb.toString();
     }
 
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ArrayElementValue.java
@@ -23,6 +23,7 @@
 
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.util.StringJoiner;
 
 /**
  * @since 6.0
@@ -35,16 +36,10 @@
     @Override
     public String toString()
     {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("{");
-        for (int i = 0; i < evalues.length; i++)
-        {
-            sb.append(evalues[i]);
-            if ((i + 1) < evalues.length) {
-                sb.append(",");
-            }
+        StringJoiner sb = new StringJoiner(",", "{", "}");
+        for (ElementValue evalue : evalues) {
+            sb.add(evalue.stringifyValue());
         }
-        sb.append("}");
         return sb.toString();
     }
 
@@ -71,16 +66,10 @@
     @Override
     public String stringifyValue()
     {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        for (int i = 0; i < evalues.length; i++)
-        {
-            sb.append(evalues[i].stringifyValue());
-            if ((i + 1) < evalues.length) {
-                sb.append(",");
-            }
+        StringJoiner sb = new StringJoiner(",", "[", "]");
+        for (ElementValue evalue : evalues) {
+            sb.add(evalue.stringifyValue());
         }
-        sb.append("]");
         return sb.toString();
     }
 
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java
@@ -24,7 +24,7 @@
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.List;
+import java.util.StringJoiner;
 
 import com.sun.org.apache.bcel.internal.classfile.ArrayElementValue;
 import com.sun.org.apache.bcel.internal.classfile.ElementValue;
@@ -102,15 +102,10 @@
     @Override
     public String stringifyValue()
     {
-        final StringBuilder sb = new StringBuilder();
-        sb.append("[");
-        String comma = "";
+        StringJoiner sb = new StringJoiner(",", "[", "]");
         for (final ElementValueGen element : evalues) {
-            sb.append(comma);
-            comma = ",";
-            sb.append(element.stringifyValue());
+            sb.add(element.stringifyValue());
         }
-        sb.append("]");
         return sb.toString();
     }
 
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java
@@ -26,7 +26,7 @@
 package com.sun.tools.javac.code;
 
 import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.StringJoiner;
 import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.AnnotationValue;
 import javax.lang.model.element.AnnotationValueVisitor;
@@ -328,16 +328,10 @@
         public void accept(Visitor v) { v.visitArray(this); }
         @DefinedBy(Api.LANGUAGE_MODEL)
         public String toString() {
-            StringBuilder buf = new StringBuilder();
-            buf.append('{');
-            boolean first = true;
+            StringJoiner buf = new StringJoiner(", ", "{", "}");
             for (Attribute value : values) {
-                if (!first)
-                    buf.append(", ");
-                first = false;
-                buf.append(value);
+                buf.add(String.valueOf(value));
             }
-            buf.append('}');
             return buf.toString();
         }
         @DefinedBy(Api.LANGUAGE_MODEL)
diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSList.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSList.java
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSList.java
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSList.java
@@ -25,7 +25,6 @@
 package sun.jvm.hotspot.utilities.soql;
 
 import java.util.*;
-import sun.jvm.hotspot.oops.*;
 
 /**
    This is JavaScript wrapper for Java List.
@@ -94,15 +93,10 @@
    }
 
    public String toString() {
-       StringBuffer buf = new StringBuffer();
-       buf.append('[');
-       for (Iterator itr = list.iterator(); itr.hasNext();) {
-           buf.append(wrapObject(itr.next()));
-           if (itr.hasNext()) {
-               buf.append(", ");
-           }
-       }
-       buf.append(']');
+      StringJoiner buf = new StringJoiner(", ", "[", "]");
+      for (Object o : list) {
+         buf.add(String.valueOf(wrapObject(o)));
+      }
        return buf.toString();
    }
 
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java
@@ -39,9 +39,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
-import java.util.Iterator;
 import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.StringJoiner;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
@@ -1144,20 +1144,10 @@
 
             @Override
             public String toString() {
-                StringBuilder sb = new StringBuilder();
-                Iterator<Node> iterator = iterator();
-                boolean first = true;
-                sb.append("succs=");
-                sb.append('[');
-                while (iterator.hasNext()) {
-                    Node input = iterator.next();
-                    if (!first) {
-                        sb.append(", ");
-                    }
-                    sb.append(input);
-                    first = false;
+                StringJoiner sb = new StringJoiner(", ", "succs=[", "]");
+                for (Node input : this) {
+                    sb.add(String.valueOf(input));
                 }
-                sb.append(']');
                 return sb.toString();
             }
         };
@@ -1178,20 +1168,10 @@
 
             @Override
             public String toString() {
-                StringBuilder sb = new StringBuilder();
-                Iterator<Node> iterator = iterator();
-                boolean first = true;
-                sb.append("inputs=");
-                sb.append('[');
-                while (iterator.hasNext()) {
-                    Node input = iterator.next();
-                    if (!first) {
-                        sb.append(", ");
-                    }
-                    sb.append(input);
-                    first = false;
+                StringJoiner sb = new StringJoiner(", ", "inputs=[", "]");
+                for (Node input : this) {
+                    sb.add(String.valueOf(input));
                 }
-                sb.append(']');
                 return sb.toString();
             }
         };
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java
@@ -26,9 +26,7 @@
 
 import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled;
 
-import java.util.Iterator;
-
-import org.graalvm.compiler.graph.iterators.NodeIterable;
+import java.util.StringJoiner;
 
 class NodeUsageIterable implements NodeIterable<Node> {
 
@@ -69,20 +67,10 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
-        Iterator<Node> iterator = iterator();
-        boolean first = true;
-        sb.append("usages=");
-        sb.append('[');
-        while (iterator.hasNext()) {
-            Node input = iterator.next();
-            if (!first) {
-                sb.append(", ");
-            }
-            sb.append(input);
-            first = false;
+        StringJoiner sb = new StringJoiner(", ", "usages=[", "]");
+        for (Node input : this) {
+            sb.add(String.valueOf(input));
         }
-        sb.append(']');
         return sb.toString();
     }
 }
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java
@@ -27,8 +27,8 @@
 import static org.graalvm.util.CollectionsUtil.anyMatch;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
+import java.util.StringJoiner;
 
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
 import jdk.vm.ci.meta.Constant;
@@ -43,7 +43,6 @@
 import org.graalvm.compiler.nodes.FixedWithNextNode;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.phases.BasePhase;
 import org.graalvm.compiler.phases.graph.MergeableState;
 import org.graalvm.compiler.phases.graph.PostOrderNodeIterator;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
@@ -185,17 +184,10 @@
         }
 
         protected static String toString(EconomicSet<ResolvedJavaType> types) {
-            StringBuilder b = new StringBuilder();
-            b.append("[");
-            Iterator<ResolvedJavaType> i = types.iterator();
-            while (i.hasNext()) {
-                ResolvedJavaType t = i.next();
-                b.append(t.toString());
-                if (i.hasNext()) {
-                    b.append(",");
-                }
+            StringJoiner b = new StringJoiner(",", "[", "]");
+            for (ResolvedJavaType t : types) {
+                b.add(t.toString());
             }
-            b.append("]");
             return b.toString();
         }
 
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java
@@ -25,7 +25,7 @@
 package org.graalvm.compiler.nodes.cfg;
 
 import java.util.ArrayList;
-import java.util.Iterator;
+import java.util.StringJoiner;
 
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
@@ -169,14 +169,11 @@
 
             @Override
             public String toString() {
-                StringBuilder str = new StringBuilder().append('[');
+                StringJoiner str = new StringJoiner(", ", "[", "]");
                 for (FixedNode node : this) {
-                    str.append(node).append(", ");
+                    str.add(String.valueOf(node));
                 }
-                if (str.length() > 1) {
-                    str.setLength(str.length() - 2);
-                }
-                return str.append(']').toString();
+                return str.toString();
             }
         };
     }
diff --git a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java
@@ -26,17 +26,13 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
 import java.util.Objects;
-import java.util.function.BiFunction;
+import java.util.StringJoiner;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
 import jdk.internal.vm.compiler.collections.EconomicSet;
 import jdk.internal.vm.compiler.collections.Equivalence;
-import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.code.SourceStackTraceBailoutException;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
@@ -48,7 +44,6 @@
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.graph.NodeStack;
 import org.graalvm.compiler.graph.Position;
-import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractEndNode;
@@ -605,15 +600,10 @@
      * @return A string of the format "[a, b, ...]".
      */
     public static String toString(Iterable<?> objects) {
-        StringBuilder str = new StringBuilder();
-        str.append("[");
+        StringJoiner str = new StringJoiner(", ", "[", "]");
         for (Object o : objects) {
-            str.append(o).append(", ");
+            str.add(String.valueOf(o));
         }
-        if (str.length() > 1) {
-            str.setLength(str.length() - 2);
-        }
-        str.append("]");
         return str.toString();
     }
 
diff --git a/src/jdk.rmic/share/classes/sun/tools/java/MethodSet.java b/src/jdk.rmic/share/classes/sun/tools/java/MethodSet.java
--- a/src/jdk.rmic/share/classes/sun/tools/java/MethodSet.java
+++ b/src/jdk.rmic/share/classes/sun/tools/java/MethodSet.java
@@ -25,7 +25,13 @@
 
 package sun.tools.java;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringJoiner;
 
 /**
  * The MethodSet structure is used to store methods for a class.
@@ -259,19 +265,11 @@
      * Returns a (big) string representation of this MethodSet
      */
     public String toString() {
-        int len = size();
-        StringBuilder sb = new StringBuilder();
+        StringJoiner sb = new StringJoiner(", ", "{", "}");
         Iterator<MemberDefinition> all = iterator();
-        sb.append("{");
-
         while (all.hasNext()) {
-            sb.append(all.next().toString());
-            len--;
-            if (len > 0) {
-                sb.append(", ");
-            }
+            sb.add(all.next().toString());
         }
-        sb.append("}");
         return sb.toString();
     }
 }
diff --git a/src/utils/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java b/src/utils/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java
--- a/src/utils/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java
+++ b/src/utils/IdealGraphVisualizer/Data/src/com/sun/hotspot/igv/data/serialization/BinaryParser.java
@@ -371,7 +371,7 @@
             sb.append(buffer.getInt());
             if (i < len - 1) {
                 sb.append(", ");
-            }
+        }
         }
         sb.append(']');
         return sb.toString().intern();
@@ -388,7 +388,7 @@
             sb.append(buffer.getDouble());
             if (i < len - 1) {
                 sb.append(", ");
-            }
+        }
         }
         sb.append(']');
         return sb.toString().intern();
@@ -399,15 +399,11 @@
         if (len < 0) {
             return "null";
         }
-        StringBuilder sb = new StringBuilder().append('[');
+        StringJoiner sj = new StringJoiner(", ", "[", "]");
         for (int i = 0; i < len; i++) {
-            sb.append(readPoolObject(Object.class));
-            if (i < len - 1) {
-                sb.append(", ");
-            }
+            sj.add(String.valueOf(readPoolObject(Object.class)));
         }
-        sb.append(']');
-        return sb.toString().intern();
+        return sj.toString().intern();
     }
 
     private <T> T readPoolObject(Class<T> klass) throws IOException {

Reply via email to