4

I am currently trying to generate a line of 60 stars however I found several ways to do it.

//Method 1
System.out.println(String.format("%60s", "").replace(' ', '*'));

//Method 2
for(int i=0;i<60;i++)
    System.out.print("*");
System.out.println("");

//Method 3
int i=0;
while(i<60) {
    System.out.print("*");
    i++;
}

Which is the best way to approach? (In terms of time and In terms of style)

And if there are any other methods to do this?

//Modular Approach, not bad
static String repeat(final String str, final int n) {
    final int len = (str == null) ? 0 : str.length();
    if (len < 1 || n < 1) {
        return "";
    }
    final StringBuilder sb = new StringBuilder(len * n);
    for (int i = 0; i < n; i++) {
        sb.append(str);
    }
    return sb.toString();
}

System.out.println(repeat("*", 60));

And

//Similar to method 1
System.out.println(new String(new char[60]).replace("\0", "*"));
Bsonjin
  • 438
  • 1
  • 4
  • 14

8 Answers8

8

How about:

Stream.generate(() -> "*").limit(60).forEach(System.out::print);
System.out.println(); // for the newline at the end

Or the slightly hacky, but one line:

System.out.println(new String(new char[60]).replace("\0", "*"));

The hacky version works because all java arrays of numeric primitives are initialized with the value 0 in all elements, which are each then replaced with the desired character once in a String.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
2

Of the methods presented, the first will likely perform best because it doesn't require a loop and only calls print once. But this smells of premature optimization. The choice of loop (for or while or do-while) is almost certainly optimized away by the compiler and JIT (depending on platform and version). However, I would prefer a fourth approach. Write Dumb Code. In this case, I would build the String with a StringBuilder and then print that. Something like,

static String repeat(final String str, final int n) {
    final int len = (str == null) ? 0 : str.length();
    if (len < 1 || n < 1) {
        return "";
    }
    final StringBuilder sb = new StringBuilder(len * n);
    for (int i = 0; i < n; i++) {
        sb.append(str);
    }
    return sb.toString();
}

and then

System.out.println(repeat("*", 60));
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
2

Most efficient? How about:

int n=60;
char[] data = new char[60];

for(int i=0; i<n; i++)
    data[i] = '*';

System.out.print(data);

Only one object generated and a single call to "print".

nimrodm
  • 23,081
  • 7
  • 58
  • 59
2

Unless you need the ability to easily modify the number of stars, I'd honestly just use System.out.println("************************************************************");

Or if you need to use the stars multiple times, which I'd assume is likely,

String sixtyStars = "************************************************************";

and then you can just pass sixtyStars to whatever printing method you need.

z-ch
  • 41
  • 4
1

In my opinions. . I think M1 is better and faster than using loops. However, M2 is easiest way to understand. Also you can add M4 by using

 PrintStart (60);\\ on call 


  \\function body 
 public static void PrintStart  ( int i){

       if (i==0)
           return; 
      System.out.print ("*");
      PrintStart  (i-1);
    }
0xFFFFFF
  • 333
  • 2
  • 13
0

In terms of time complexity, they are the same: O(n). However M2=M3 better than M1 (It actually contains loops - you must see the source code of String.format and String.replace).

In terms of space complexity, M.2 is better.

In this problem M.2 is enough, can be improved by using StringBuilder.

T D Nguyen
  • 7,054
  • 4
  • 51
  • 71
0

What about using custom collector?

String result = IntStream.range(0, 60).mapToObj(i -> '*')
        .collect(Collector.of(
                StringBuilder::new,
                StringBuilder::append,
                StringBuilder::append,
                StringBuilder::toString));

or the same with joining Strings

String result = IntStream.range(0, 60).mapToObj(i -> "*")
        .collect(Collectors.joining());
ytterrr
  • 3,036
  • 6
  • 23
  • 32
0

Here's one I have used regularly - using Java 8 streams:

Stream.generate(() -> "*").limit(60).collect(Collectors.joining());

For me it captures the intent well: generate a stream of asterisks, get the first 60 and join them together.

sprinter
  • 27,148
  • 6
  • 47
  • 78