Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4642733

Use StringBuffer instead of String concatenation

    XMLWordPrintable

Details

    • Enhancement
    • Resolution: Won't Fix
    • P4
    • None
    • 1.3.0
    • core-libs
    • x86
    • windows_98

    Description



      Name: jl125535 Date: 02/25/2002


      FULL PRODUCT VERSION :
      java version "1.4.0-rc"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-rc-b91)
      Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      There are many places where code like this

         String x = someString + anotherString;

      occurs in the JDK class source.

      As the compiler converts the expression to use a
      StringBuffer and StringBuffer initially has an internal
      buffer length of 16, if the resulting String is over 16
      characters long aditional new char[] memory allocations and
      garbage collection is required within StringBuffer.

         StringBuffer xx = new StringBuffer(someString.length() +
      anotherString.length();
         xx.append(someString).append(anotherString);
         String x = xx.toString();


      A 15-20% improvement in speed can be expected;

      -------------------------------------------------------------------------------
      Here is a list of locations that use direct String concatenation.

      I've ignored direct String concatenation in Exception throw statements
      and some debugging code, since this code is called rarely. For those
      cases, speed is less important than the greater readability and
      slight reduction in text size.


      java.util.jar.Attributes.writeMain()

                  out.writeBytes(vername+": "+version+"\r\n");

         is probably better as

                  out.writeBytes(vername);
                  out.writeBytes(": ");
                  out.writeBytes(version);
                  out.writeBytes("\r\n");



      java.util.jar.Attributes.read()

         value should probably be a StringBuffer, but this is complicated by
         using the deprecated String constructor. Should probably use
             public String(byte bytes[], int offset, int length, String
      charsetName)
         string constructor.

      java.util.jar.Manifest.read(InputStream is)

         name may be better as a StringBuffer, but this is complicated by
         using the deprecated String constructor. Should probably use
             public String(byte bytes[], int offset, int length, String
      charsetName)
         string constructor.


      java.util.logging.ConsoleHandler.configure()

         4 occurances of cname +".level", or similar; as this
         is a one off configuration then it is probably not
         worth converting.

      java.util.logging.ErrorManager.error()

              String text = "java.util.logging.ErrorManager: " + code;
              if (msg != null) {
                  text = text + ": " + msg;
              }
              System.err.println(text);

         should be

              StringBuffer text = new
      StringBuffer(1024).append("java.util.logging.ErrorManager:
      ").append(code);
              if (msg != null) {
                  text.append(": ").append(msg);
              }
              System.err.println(text.toString());

         a size of 1024 should take care of all but the very longest msg
      Strings.


      java.util.logging.FileHandler.configure()

         8 occurances of cname +".level", or similar; as this
         is a one off configuration then it is probably not
         worth converting.

      java.util.logging.FileHandler.generate()

         The String word is appended in multiple places, converting
         it to a StringBuffer would probably save space and would be
         quicker.

      java.util.logging.LogManager.addLogger()

         A couple of occurances of appending ".level" to a String
         probably not worth converting.

      java.util.logging.LogManager.readConfiguration()

                      System.err.println("" + ex);

         should this not be

                      System.err.println(ex.toString());


      java.util.logging.LogManager.AccessController.doPrivileged()

         One occurance of String "+", but its probably not worth
         converting to use StringBuffer.


                      System.err.println("" + ex);

         should this not be

                      System.err.println(ex.toString());

                  
      java.util.logging.MemoryHandler.configure()

         6 occurances of cname +".level", or similar; as this
         is a one off configuration then it is probably not
         worth converting.


      java.util.logging.MemoryHandler.MemoryHandler()

                      System.err.println("" + ex);

         should this not be

                      System.err.println(ex.toString());


      java.util.logging.SocketHandler.configure()

         6 occurances of cname +".level", or similar; as this
         is a one off configuration then it is probably not
         worth converting.



      java.util.logging.StreamHandler.configure()

         6 occurances of cname +".level", or similar; as this
         is a one off configuration then it is probably not
         worth converting.


      java.util.prefs.AbstractPreferences.AbstractPreferences()

                  absolutePath = (parent==root ? "/" + name
                                               : parent.absolutePath() + "/"
      + name);

      should probably be

                  if (parent==root) {
                     absolutePath = "/" + name;
                  } else {
                     String pap = parent.absolutePath();
                     StringBuffer sb = new
      StringBuffer(pap.length()+1+name.length());
                     sb.append(pap).append("/")+append(name);
                     absolutePath = sb.toString();
                  }



      java.util.prefs.AbstractPreferences.toString()

              return (this.isUserNode() ? "User" : "System") +
                     " Preference Node: " + this.absolutePath();


         should probably be

              StringBuffer sb = new StringBuffer(1024); // should be long
      enough
              this.isUserNode() ? sb.append("User") : sb.append("System");
              return sb.append(" Preference Node:
      ").append(this.absolutePath()).toString();



      java.util.prefs.Preferences.nodeName()

              return "/" + packageName.replace('.', '/');

         should probably be

              StringBuffer sb = new StringBuffer(1+packageName.length());
              return sb.append("/").append(packageName.replace('.', '/'));


      java.util.regex.Matcher.appendReplacement()

         groupString does not seem to be required.


              String s = replacement;
              StringBuffer result = null;

              // If no match, return error
              if (first < 0)
                  throw new IllegalStateException("No match available");

              // Process substitution string to replace group references
      with groups
              int cursor = 0;
              result = new StringBuffer();

         could be


              // If no match, return error
              if (first < 0)
                  throw new IllegalStateException("No match available");

              // Process substitution string to replace group references
      with groups
              int cursor = 0;
              String s = replacement;
              StringBuffer result = new StringBuffer();


      java.util.regex.Matcher.appendTail()

              String tail = getSubSequence(lastAppendPosition,
      getTextLength()).toString();
              sb.append(tail);

         could be:

              sb.append(getSubSequence(lastAppendPosition,
      getTextLength()));



      java.util.regex.Pattern.normalize()

              StringBuffer newPattern = new StringBuffer();

         could be:

              StringBuffer newPattern = new StringBuffer(patternLength*2);
      // unlikely to more than double in size


         and

                      newPattern.append("(?:" + ea + ")");

         could be:

                      newPattern.append("(?:").append(ea).append(")");




      java.util.regex.Pattern.normalizeCharClass()

                  result = new String("(?:"+charClass.toString()+
                                      eq.toString()+")");

         could be:

                  StringBuffer sb = new
      StringBuffer(4+charClass.getLength()+eq.getLength());
                  sb.append("(?:").append(charClass).append(eq).append(")");
                  result = sb.toString();



      java.util.regex.Pattern.produceEquivalentAlternation()

              // Add combined permutations
              for(int x=0; x<perms.length; x++) {
                  String next = base + perms[x];
                  if (x>0)
                      result.append("|"+next);
                  next = composeOneStep(next);
                  if (next != null)
                      result.append("|"+produceEquivalentAlternation(next));
              }

      could be:

              // Add combined permutations
              StringBuffer next = new StringBuffer(1024);
              for(int x=0; x<perms.length; x++) {
                  next.setLength(0);
                  next.append(base).append(perms[x]);
                  if (x>0)
                      result.append("|").append(next);
                  next = composeOneStep(next);
                  if (next != null)
                      result.append("|").append(produceEquivalentAlternation(next)));
              }


          private StringBuffer composeOneStep(StringBuffer input) {
              String firstTwoChars = input.substring(0,2);
              String result = Normalizer.compose(firstTwoChars, false, 0);

              if (result.equals(firstTwoChars))
                  return null;
              else {
                  String remainder = input.substring(2);
                  input.setLength(0);
                  return input.append(result).append(remainder);
              }
          }

      or even further reduced to:

              StringBuffer next = new StringBuffer(1024);
              for(int x=0; x<perms.length; x++) {
                  next.setLength(0);
                  next.append(base).append(perms[x]);
                  if (x>0) {
                      result.append("|").append(next);
                  }
                  String firstTwoChars = next.substring(0,2);
                  String result = Normalizer.compose(firstTwoChars, false,
      0);

                  if (! result.equals(firstTwoChars) ) {
                      String remainder = next.substring(2);
                      next.setLength(0);
                      next.append(result).append(remainder);
                      result.append("|").append(produceEquivalentAlternation(next)));
                  }
              }


         Nothing to do with StringBuffers, but there seems to be scope for
         factorizing out the cases of:

              boolean study(TreeInfo info) {
                  info.minLength++;
                  info.maxLength++;
                  return next.study(info);
              }

         into a SingleCharNode extending Node and then subclasses of
         Node (SingleA, SingleU, etc.) could extend this.


      (Review ID: 139191)
      ======================================================================

      Attachments

        Issue Links

          Activity

            People

              mmcclosksunw Michael Mccloskey (Inactive)
              jleesunw Jon Lee (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: