0

If I initialize String array directly like this String[] Distro = Distros.split(","); then it'll create an object because variable Distro is holding the array.

But If I do it this way then it'll also create an object?

        String Distros = "CentOS,RHEL,Debian,Ubuntu";

        for (String s : Distros.split(",")) {
            System.out.println(s);
        }

My goal is to reduce object creation to minimize garbage.

HyperX Pro
  • 158
  • 2
  • 9
  • 2
    Yes. You will still generate a `String[]`, and it will be eligible for garbage collection after your loop. – Elliott Frisch May 13 '20 at 20:32
  • Strings are objects. For a String to exist whether that be a `String str = "abcd"` or `String[]...` an object is created. The reference lives on the stack and the object lives on the heap. Once the object on the heap is no longer referenced from the stack it becomes eligible for the GC. – Bradley May 13 '20 at 20:38
  • https://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work – Sotirios Delimanolis May 13 '20 at 20:48
  • Are you asking if the foreach is creating a copy of the object returned by `Distros.split(",")`? – Sotirios Delimanolis May 13 '20 at 20:48
  • Why do you want to minimise garbage? The JVM is really good at cleaning up after itself. Garbage doesn't live long. – Dawood ibn Kareem May 13 '20 at 20:50
  • @SotiriosDelimanolis Not exactly. Till now my understanding was if we initialize an object by saying `Object o = new Object` then only it'll create object else not. So in my sense `String s : Distros.split(",")` was not creating an object. But now doubts are cleared. Even `String s : Distros.split(",")` creates an object. – HyperX Pro May 13 '20 at 20:52
  • How was the loop supposed to work if there was no object? – Sotirios Delimanolis May 13 '20 at 20:53
  • @SotiriosDelimanolis Yeah, I get it now. – HyperX Pro May 13 '20 at 20:55
  • @DawoodibnKareem I am working on a high-performance application and creating too many objects too fast is a problem. The GC pauses application execution while collecting garbage and this creates problem. – HyperX Pro May 13 '20 at 20:59
  • But this is simply how Java programs work. They create objects, then those objects get garbage collected. The people who make Java have put a lot of effort into making the garbage collector as efficient and undisruptive as possible. All Java programs except the most trivial ones create lots of objects. – Dawood ibn Kareem May 13 '20 at 21:02
  • Yeah, but I'm trying my best to minimize garbage so I thought to get some doubts cleared here. – HyperX Pro May 13 '20 at 21:07

2 Answers2

2

Your reasoning “then it'll create an object because variable Distro is holding the array” indicates that you are confusing object creation with variable assignment.

The object is created by the expression Distros.split(","), not the subsequent assignment. It should become obvious when you consider that the split method is an ordinary Java method creating and returning the array without any knowledge about what the caller will do with the result.

When the operation happens in a performance critical code, you might use

int p = 0;
for(int e; (e = Distros.indexOf(',', p)) >= 0; p = e+1)
    System.out.println(Distros.substring(p, e));
System.out.println(Distros.substring(p));

instead. It’s worth pointing out that this saves the array creation but still performs the creation of the substrings, which is the more expensive aspect of it. Without knowing what you are actually going to do with the substrings, it’s impossible to say whether there are alternatives which can save the substring creation¹.

But this loop still has an advantage over the split method. The split method creates all substrings and returns an array holding references to them, forcing them to exist at the same time, during the entire loop. The loop above calls substring when needed and doesn’t keep a reference when going to the next. Hence, the strings are not forced to exist all the time and the garbage collector is free to decide when to collect them, depending on the current memory utilization.


¹ I assume that printing is just an example. But to stay at the example, you could replace

    System.out.println(Distros.substring(p, e));

with

    System.out.append(Distros, p, e).println();

The problem is, this only hides the substring creation, at least in the reference implementation which will eventually perform the substring creation behind the scenes.

An alternative is

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
                        new FileOutputStream(FileDescriptor.out)));
try {
    int p = 0; for(int e; (e = Distros.indexOf(',', p)) >= 0; p = e+1) {
        bw.write(Distros, p, e - p);
        bw.write(System.lineSeparator());
    }
    bw.write(Distros, p, Distros.length() - p);
    bw.write(System.lineSeparator());
    bw.flush();
}
catch(IOException ex) {
    ex.printStackTrace();
}

which truly writes the strings without creating substrings. But it forces us to deal with potential exceptions, which PrintStream normally hides.

Holger
  • 285,553
  • 42
  • 434
  • 765
1

The method split(delimiter) returns string array from the string based on the delimiter, what you did create the string array in for each and the scope of it ended after for each so It's eligible for GC to release it

    String Distros = "CentOS,RHEL,Debian,Ubuntu";
    for (String s : Distros.split(",")) {
        System.out.println(s);
    }

, Is equivalent to

    String Distros = "CentOS,RHEL,Debian,Ubuntu";

    System.out.println("start scope");
    {
      String[] splitArray = Distros.split(",");
      for (String s : splitArray) {
        System.out.println(s);
      }
    }
    System.out.println("end scope");
0xh3xa
  • 4,801
  • 2
  • 14
  • 28
  • Let's say the split String array has 100K elements. When for loop starts, will it call `split(delimiter)` for 100K times? – HyperX Pro May 13 '20 at 20:41
  • No, let me put some more details in the post – 0xh3xa May 13 '20 at 20:42
  • Saw the updated answer. Now my question is, is it better to create this `String[] splitArray = Distros.split(",");` if I want to use `Distros.split(",")` 2 or more times to minimize object creation? – HyperX Pro May 13 '20 at 20:48
  • As you like if you want to use `splitArray` in another operation keep it in a variable – 0xh3xa May 13 '20 at 20:49