简体   繁体   中英

Use of StringBuilder vs String in Java

I have a loop thats constantly setting new values to a few string and looking into it, i thought that i could improve it. At first it was easy (this is how it actually looks) but i am looking for a way to avoid doing that lot of "ToString" and then resetting that string to "".

private void obtenerProfCita(JSONArray catalogoDatos) {
        String areaConsumer = "";
        String resourceConsumer = "";
        String activityConsumerid = "";
        for(int i = 0; i < catalogoDatos.length(); i++) {
            areaConsumer = catalogoDatos.getJSONObject(i).get("area_consumerid").toString();
            resourceConsumer = catalogoDatos.getJSONObject(i).get("resource_consumerid").toString();
            activityConsumerid = catalogoDatos.getJSONObject(i).get("activity_consumerid").toString();
            if(StringUtils.isNotBlank(areaConsumer) && StringUtils.isNotBlank(resourceConsumer) && StringUtils.isNotBlank(activityConsumerid)) {
                log.error("REFERENCIA TUOTEMPO:\nModulo: " + i + "\nCONSUL: " + areaConsumer + "\nIDPROF: " + resourceConsumer);
                TuotempoDAO.guardarActivityId(catalogoDatos.getJSONObject(i));//Guardar en BBDD el Activity_ID
            }
            areaConsumer = "";
            resourceConsumer = "";
        }
    }

As you can see, is a basic for loop but taking in account that the JSONArray is quite big, i was looking for a way to use StringBuilders or StringBuffers and avoid the "ToStrings" in the JSON array.

Actual code with stringBuilders:

private void obtenerProfCita(JSONArray catalogoDatos) {
        StringBuilder areaConsumer = new StringBuilder();
        StringBuilder resourceConsumer = new StringBuilder();
        StringBuilder activityConsumerid = new StringBuilder();
        for(int i = 0; i < catalogoDatos.length(); i++) {
            areaConsumer.append(catalogoDatos.getJSONObject(i).get("area_consumerid").toString());
            resourceConsumer.append(catalogoDatos.getJSONObject(i).get("resource_consumerid").toString());
            activityConsumerid.append(catalogoDatos.getJSONObject(i).get("activity_consumerid").toString());
            if(StringUtils.isNotBlank(areaConsumer) && StringUtils.isNotBlank(resourceConsumer) && StringUtils.isNotBlank(activityConsumerid)) {
                log.error("REFERENCIA TUOTEMPO:\nModulo: " + i + "\nCONSUL: " + areaConsumer + "\nIDPROF: " + resourceConsumer);
                TuotempoDAO.guardarActivityId(catalogoDatos.getJSONObject(i));//Guardar en BBDD el Activity_ID
            }
            areaConsumer.setLength(0);
            resourceConsumer.setLength(0);
        }
    }

Also i have doubts about how efficient is to use StringBuilder instead of String, if someone could explain it to me it would be great.

EDIT. Thanks to OH GOD SPIDERS below, i have improved a little my code. here it´s how it looks right now:

private void obtenerProfCita(JSONArray catalogoDatos) {
        StringBuilder areaConsumer = new StringBuilder();
        StringBuilder resourceConsumer = new StringBuilder();
        StringBuilder activityConsumerid = new StringBuilder();
        for(int i = 0; i < catalogoDatos.length(); i++) {
            areaConsumer.append(catalogoDatos.getJSONObject(i).get("area_consumerid"));
            resourceConsumer.append(catalogoDatos.getJSONObject(i).get("resource_consumerid"));
            activityConsumerid.append(catalogoDatos.getJSONObject(i).get("activity_consumerid"));
            if (StringUtils.isNotBlank(areaConsumer) 
                    && StringUtils.isNotBlank(resourceConsumer) 
                      && StringUtils.isNotBlank(activityConsumerid)) {
                log.error("REFERENCIA TUOTEMPO:\nModulo: " + i + "\nCONSUL: " + areaConsumer + "\nIDPROF: " + resourceConsumer);
                TuotempoDAO.guardarActivityId(catalogoDatos.getJSONObject(i));//Guardar en BBDD el Activity_ID
            }
            areaConsumer.setLength(0);
            resourceConsumer.setLength(0);
            activityConsumerid.setLength(0);
        }
    }

Any help is appreciatted

EDIT2:

Thank you for all the help, i will modify my code taken in account the last comment and answers.

The difference, when concatenating lots of Strings in a loop is that:

  • concatenating Strings in a loop with eg += creates lots of new intermediate Strings
  • StringBuilder doesn't, it collects all the Strings, then builds a new one at the end (actually I think it has an array/array list of chars that gets filled, but the details don't matter here). Less memory used, less copying characters around.

Doesn't matter much for small amounts of Strings, but if your array is big it should be noticeable.

Your loop is not appending to the strings and therefore using StringBuilder gives no performance improvements.

I would only do two things:

  • move the declaration of the variables into the loop
  • only fetch catalogoDatos.getJSONObject(i) once and store that reference in a local variable

This gives the following code:

private void obtenerProfCita(JSONArray catalogoDatos) {
    for (int i = 0; i < catalogoDatos.length(); i++) {
        JSONObject o = catalogoDatos.getJSONObject(i);
        String areaConsumer = o.get("area_consumerid").toString();
        String resourceConsumer = o.get("resource_consumerid").toString();
        String activityConsumerid = o.get("activity_consumerid").toString();
        if (StringUtils.isNotBlank(areaConsumer) && StringUtils.isNotBlank(resourceConsumer) && StringUtils.isNotBlank(activityConsumerid)) {
            log.error("REFERENCIA TUOTEMPO:\nModulo: " + i + "\nCONSUL: " + areaConsumer + "\nIDPROF: " + resourceConsumer);
            TuotempoDAO.guardarActivityId(o);//Guardar en BBDD el Activity_ID
        }
    }
}

About the idea that StringBuilder.append() somehow works around the need for toString() :

What do you think how StringBuilder.append() does append the string representation of an object?

Great surprise: it uses toString() internally.

Actually, if you look at the internals of StringBuilder.append(Object) :

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

it calls String.valueOf(obj) which is

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Effectively the only difference between

stringBuilder.append(obj);

and

stringBuilder.append(obj.toString());

is that first version correctly handles the case where obj is null whereas in the second case it will throw a NullPointerException .

stringbuilder 创建一个对象,但对于 '+',每次使用都会创建一个新的 Stringbuilder 对象并使用一次 tostring()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM