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.

11
  • 2
    Yes. You will still generate a String[], and it will be eligible for garbage collection after your loop. Commented May 13, 2020 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. Commented May 13, 2020 at 20:38
  • stackoverflow.com/questions/85190/… Commented May 13, 2020 at 20:48
  • Are you asking if the foreach is creating a copy of the object returned by Distros.split(",")? Commented May 13, 2020 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. Commented May 13, 2020 at 20:50

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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");

4 Comments

Let's say the split String array has 100K elements. When for loop starts, will it call split(delimiter) for 100K times?
No, let me put some more details in the post
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?
As you like if you want to use splitArray in another operation keep it in a variable

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.