Search code examples
javajsonstringstringbuilder

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.


Solution

  • 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.