miércoles, 2 de junio de 2010

cadenas en java (strings)

En java, como en muchos lenguajes de programacion modernos, existe una clase que define la representacion interna de una cadena durante la ejecucion del programa. En java esta clase es String. Internamente, la clase String, esta representada por un arreglo del tipo nativo char. Derivado de esto, la maquina virtual de java, maneja las cadenas como un conjunto de caracteres codificados en Unicode en formato UTF-16 (No UTF-8, no ASCII). Una consecuencia es que cada caracter que conforma la cadena, utiliza 2 bytes.

Una situacion que se da debido a la restriccion de inmutabilidad, es que los constructores que reciben un arreglo de caracteres (char[]) deben generar un arreglo interno nuevo y copiar el original (total o parcialmente, segun sea el caso), dependiendo del constructor que se emplee.

En cambio, cuando se genera una cadena utilizando otra cadena como base, es posible compartir el arreglo internamente, pues la fuente inmutable por definicion. En algunas situaciones, se puede generar un nuevo arreglo interno, para evitar el uso de memoria.

Cuando se necesita extraer un caracter de una cadena, es preferible utilizar la funcion charAt, en vez de un substring. Dado que esta funcion regresa un valor directamente (el iesimo caracter en el arreglo) sin necesidad de crear objetos y utilizando exclusivamente el stack, en cambio substring crea un nuevo objeto String, que puede compartir la memoria empleada por la cadena original. Una prueba de esto, es ejecutar el siguiente codigo:

        String s = "test";
        long start = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            s.substring(0,1);
        }
        System.out.println(System.currentTimeMillis() - start);

Contra este codigo

        String s = "test";
        long start = System.currentTimeMillis();
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            s.charAt(0);
        }
        System.out.println(System.currentTimeMillis() - start);

El primer codigo, puede llegar a ejecutarse en unos cuantos milisegundos (30 aprox en un Centrino Duo a 1.83GHz), mientras que el segundo codigo se tarda mas de 200 veces mas tiempo (casi 1 minuto en el mismo procesador), particularmente, cuando se ejecuta la maquina virtual con la opcion -server, cuando se ejecuta con la opcion -client, los tiempos de ejecucion del primer ejemplo es de 1/3 con respecto al segundo ejemplo. Este codigo optimizado esta empleado en el post "Extraccion del nombre de una propiedad del getter respectivo en java".

La funcion concat, es optima cuando se emplea exclusivamene con 2 cadenas, pues se aloja exactamente la memoria necesaria para construir la nueva cadena, cuya longitud es la suma de ambas longitudes.


No hay comentarios.:

Publicar un comentario