Use StringBuilder to pad String with blank spaces or other characters
Asked Answered
S

5

14

I'm a beginner to java and this is my first post on Stackoverflow. Although my initial code is similar to other posts here, my question relates to implementing StringBuilder and so the reason for this post.

I've created a method

**Initial code**
private static String padAgain(String result,int padNum)  
    {  
          String str = "";  
          for(int i = padNum; i >= 0; i--)  
        {  
            str = String.format("%" + padNum + "s", result).replace(" ", "*");  
        }  
          return str;  
    }  

to left pad the string with blank spaces (or special characters) using String.format method. I'm using the same in my program to right justify numbers. Numbers start with 2 (single-digit) and increase in multiples of 2 (containing n no. of digits) with the spaces being inversely proportional to the increase in digits.

Here is the output for illustrative purposes:

    Enter exponent value for base-2 - Enter 0 to exit: 
128
Square    1: **************************************2 items
Square    2: **************************************4 items
Square    3: **************************************8 items
Square    4: *************************************16 items
Square    5: *************************************32 items
Square    6: *************************************64 items
Square    7: ************************************128 items
Square    8: ************************************256 items
Square    9: ************************************512 items
Square   10: ***********************************1024 items
Square   11: ***********************************2048 items
Square   12: ***********************************4096 items
Square   13: ***********************************8192 items
Square   14: **********************************16384 items
Square   15: **********************************32768 items
Square   16: **********************************65536 items
Square   17: *********************************131072 items
Square   18: *********************************262144 items
Square   19: *********************************524288 items
Square   20: ********************************1048576 items
Square   21: ********************************2097152 items
Square   22: ********************************4194304 items
Square   23: ********************************8388608 items
Square   24: *******************************16777216 items
Square   25: *******************************33554432 items
Square   26: *******************************67108864 items
Square   27: ******************************134217728 items
Square   28: ******************************268435456 items
Square   29: ******************************536870912 items
Square   30: *****************************1073741824 items
Square   31: *****************************2147483648 items
Square   32: *****************************4294967296 items
Square   33: *****************************8589934592 items
Square   34: ****************************17179869184 items
Square   35: ****************************34359738368 items
Square   36: ****************************68719476736 items
Square   37: ***************************137438953472 items
Square   38: ***************************274877906944 items
Square   39: ***************************549755813888 items
Square   40: **************************1099511627776 items
Square   41: **************************2199023255552 items
Square   42: **************************4398046511104 items
Square   43: **************************8796093022208 items
Square   44: *************************17592186044416 items
Square   45: *************************35184372088832 items
Square   46: *************************70368744177664 items
Square   47: ************************140737488355328 items
Square   48: ************************281474976710656 items
Square   49: ************************562949953421312 items
Square   50: ***********************1125899906842624 items
Square   51: ***********************2251799813685248 items
Square   52: ***********************4503599627370496 items
Square   53: ***********************9007199254740992 items
Square   54: **********************18014398509481984 items
Square   55: **********************36028797018963968 items
Square   56: **********************72057594037927936 items
Square   57: *********************144115188075855872 items
Square   58: *********************288230376151711744 items
Square   59: *********************576460752303423488 items
Square   60: ********************1152921504606846976 items
Square   61: ********************2305843009213693952 items
Square   62: ********************4611686018427387904 items
Square   63: ********************9223372036854775808 items
Square   64: *******************18446744073709551616 items
Square   65: *******************36893488147419103232 items
Square   66: *******************73786976294838206464 items
Square   67: ******************147573952589676412928 items
Square   68: ******************295147905179352825856 items
Square   69: ******************590295810358705651712 items
Square   70: *****************1180591620717411303424 items
Square   71: *****************2361183241434822606848 items
Square   72: *****************4722366482869645213696 items
Square   73: *****************9444732965739290427392 items
Square   74: ****************18889465931478580854784 items
Square   75: ****************37778931862957161709568 items
Square   76: ****************75557863725914323419136 items
Square   77: ***************151115727451828646838272 items
Square   78: ***************302231454903657293676544 items
Square   79: ***************604462909807314587353088 items
Square   80: **************1208925819614629174706176 items
Square   81: **************2417851639229258349412352 items
Square   82: **************4835703278458516698824704 items
Square   83: **************9671406556917033397649408 items
Square   84: *************19342813113834066795298816 items
Square   85: *************38685626227668133590597632 items
Square   86: *************77371252455336267181195264 items
Square   87: ************154742504910672534362390528 items
Square   88: ************309485009821345068724781056 items
Square   89: ************618970019642690137449562112 items
Square   90: ***********1237940039285380274899124224 items
Square   91: ***********2475880078570760549798248448 items
Square   92: ***********4951760157141521099596496896 items
Square   93: ***********9903520314283042199192993792 items
Square   94: **********19807040628566084398385987584 items
Square   95: **********39614081257132168796771975168 items
Square   96: **********79228162514264337593543950336 items
Square   97: *********158456325028528675187087900672 items
Square   98: *********316912650057057350374175801344 items
Square   99: *********633825300114114700748351602688 items
Square  100: ********1267650600228229401496703205376 items
Square  101: ********2535301200456458802993406410752 items
Square  102: ********5070602400912917605986812821504 items
Square  103: *******10141204801825835211973625643008 items
Square  104: *******20282409603651670423947251286016 items
Square  105: *******40564819207303340847894502572032 items
Square  106: *******81129638414606681695789005144064 items
Square  107: ******162259276829213363391578010288128 items
Square  108: ******324518553658426726783156020576256 items
Square  109: ******649037107316853453566312041152512 items
Square  110: *****1298074214633706907132624082305024 items
Square  111: *****2596148429267413814265248164610048 items
Square  112: *****5192296858534827628530496329220096 items
Square  113: ****10384593717069655257060992658440192 items
Square  114: ****20769187434139310514121985316880384 items
Square  115: ****41538374868278621028243970633760768 items
Square  116: ****83076749736557242056487941267521536 items
Square  117: ***166153499473114484112975882535043072 items
Square  118: ***332306998946228968225951765070086144 items
Square  119: ***664613997892457936451903530140172288 items
Square  120: **1329227995784915872903807060280344576 items
Square  121: **2658455991569831745807614120560689152 items
Square  122: **5316911983139663491615228241121378304 items
Square  123: *10633823966279326983230456482242756608 items
Square  124: *21267647932558653966460912964485513216 items
Square  125: *42535295865117307932921825928971026432 items
Square  126: *85070591730234615865843651857942052864 items
Square  127: 170141183460469231731687303715884105728 items
Square  128: 340282366920938463463374607431768211456 items
Enter exponent value for base-2 - Enter 0 to exit:
0

When the iterations increase exponentially, say from 2^10 to 2^128, then the String.format() seems to be a tad slow. So, I replaced String.format with StringBuilder and met only with partial success.

[sidebar]I've not posted rest of the program code for brevity and also my focus is on padAgain(String,int) method shown.If required, will post entire code.[/sidebar]

**Initial code modified**
private static String padAgain(String result,int padNum)
    {
        StringBuilder sb = new StringBuilder(result);
        for(int i = 1; i < padNum; i++)
        {
              sb.insert(0, result).insert(sb.indexOf(result), " ").setLength(padNum - result.toCharArray().length);   
        }
        sb.append(result);
        return sb.toString();
    }

and its output

Enter exponent value for base-2 - Enter 0 to exit: 
16
Square    1:  2 22 items
Square    2:  4 44 items
Square    3:  8 88 items
Square    4:  1616 items
Square    5:  3232 items
Square    6:  6464 items
Square    7:  1128 items
Square    8:  2256 items
Square    9:  5512 items
Square   10:  1024 items
Square   11:  2048 items
Square   12:  4096 items
Square   13:  8192 items
Square   14: 16384 items
Square   15: 32768 items
Square   16: 65536 items
Enter exponent value for base-2 - Enter 0 to exit: 
0

Code explained (what I'm attempting to do):

  • variable 'padNum' stores the maximum length of the exponent value, being 65536 of max. length 5
  • variable 'result' is a String representation of numbers starting with 2
  • for loop to iterate till max. length is reached
  • StringBuilder object to insert the String value at index 0. Within this, invoke the indexOf(String) by passing 'result' as a substring of itself and insert blank space at position 0 upto max.length - length of each number
  • finally append 'result' to make up the max. length and
  • return as String value to calling object

Much appreciated if the forum experts/members could help expand/further modify/correct my StringBuilder code.

Sanguinaria answered 9/8, 2012 at 9:45 Comment(2)
What is the question? Which partial success are you referring to? It seems like it does what you intended seeing from the sample output?Barraza
@Hiery, No. My intention is to left pad the nos. with spaces and it does so only for the 5 & 4-digit nos. in the sample output. For the 3,2 & single-digit nos., it prints the no. instead of the blank space. - javabegins293Sanguinaria
V
8

How about simplifying this?

  • padnum is the maximal length of your String
  • result.length is the length already used
  • so you can calculate how many placeholders you need align the string right by substracting the alligned string from the overall size.

    StringBuilder sb = new StringBuilder();
    int rest = padnum - result.length();
    for(int i = 1; i < rest; i++)
        {
             sb.append(" ");
        }
    sb.append(result);
    return sb.toString();
    

This calculates how many spaces have to be added and adds them. (with a StringBuilder, this is relatively fast) at the end it adds your result.

Velarde answered 9/8, 2012 at 9:59 Comment(1)
@Kostronor, the code is indeed simplified :). From the looks of it, I've unnecessarily complicated with multiple insert calls et al. Thank you so much! - javabegins293Sanguinaria
U
8

You can also something really simpler with the fill() method of Arrays.

StringBuilder sb = new StringBuilder();
char[] pad = new char[padnum - result.length()];
Arrays.fill(pad, '*');
return sb.append(pad).append(result).toString();

We are in really little times but this method is about 25% faster than the for loop one.

Ungotten answered 25/10, 2013 at 7:38 Comment(0)
M
5

Kostronor's approach is awesome, but just for a little bit of different perspetive

public String pad(String value, int length) {
    return pad(value, length, " ");
}

public String pad(String value, int length, String with) {
    StringBuilder result = new StringBuilder(length);
    result.append(value);

    while (result.length() < length) {
        result.insert(0, with);
    }

    return result.toString();
}

Now you could reverse the idea with result.append(with); to "fill out" a String

ANOTHER IDEA

If we want to reduce the possibility of the internal arraycopy causing us any additional overhead (thanks to Kostonor for pointing it out ;)), we could instead do:

public String fill(int length, String with) {
    StringBuilder sb = new StringBuilder(length);
    while (sb.length() < length) {
        sb.append(with);
    }
    return sb.toString();
}

public String pad(String value, int length) {
    return pad(value, length, " ");
}

public String pad(String value, int length, String with) {
    StringBuilder result = new StringBuilder(length);
    // Pre-fill a String value
    result.append(fill(Math.max(0, length - value.length()), with));
    result.append(value);

    return result.toString();
}

The benefit is you gain some additional methods that can be used to build different solutions.

For example if we include:

public String fill(String value, int length, String with) {

    StringBuilder result = new StringBuilder(length);
    result.append(value);
    result.append(fill(Math.max(0, length - value.length()), with));

    return result.toString();

}

And then execute

System.out.println("PAD: " + pad("Testing", 12, "*"));
System.out.println("PAD: " + pad("1", 12, "*"));
System.out.println("FILL: " + fill("1", 12, "*"));
System.out.println("FILL: " + fill("Testing", 12, "*"));

We get

PAD: *****Testing
PAD: ***********1
FILL: 1***********
FILL: Testing*****

Thanks to Kostronor for been a good sport and making me think about my ideas a little more ;)

Mooney answered 9/8, 2012 at 10:10 Comment(2)
That also is a good idea! Have in mind that the Builder has to shift the whole String one char forward every time you insert a new space. There will be no noticeable impact with this in a small scope and it is definitely more readable but not my favorite solution ;)Velarde
Oh, agreed, it's just another perspective on the problem ;). Having looked at the StringBuilder code, insert and append are almost the same thing, except insert needs to do an arraycopy. Having set the length of the StringBuilder at the start, should ensure that no time is wasted in trying to make more room for the new text, but the arraycopy is still going to add a (small) amount of overheadMooney
V
0

This can be significantly simplified with Java 11 and it uses array copoy internally, string concatentation should also be converted to stringbuilder internally

public static String padNum(int number, String pad, int length){
    String numString = String.valueOf(number);
    int padLength = length - numString.length();
    if(padLength > 0)
        return pad.repeat(padLength) + numString;
    else
        return numString;
}

check if rest is more than 0 to see if we need a pad or not, then use String.repeat to generate a pad of the right size

the string length will always be >= padLength

Venosity answered 8/9, 2020 at 23:24 Comment(0)
D
0

Use

String stars = "*".repeat(i);
sb.append(stars);

From the javadocs:

repeat

public String repeat​(int count) Returns a string whose value is the concatenation of this string repeated count times.

If this string is empty or count is zero then the empty string is returned.

Parameters: count - number of times to repeat Returns: A string composed of this string repeated count times or the empty string if this string is empty or count is zero Throws: IllegalArgumentException - if the count is negative. Since: 11

Desegregate answered 5/10, 2020 at 12:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.