Concatenando Strings en Java

Publicado el 4 de March de 2007 por Paco

Es un truco muy conocido y lo recuerdan en esta entrada de javaHispano.

Cuando se usa el operador “+” con dos instancias de String, el compilador, lo que hace es sustituir la operación por la creación de un StringBuffer.

En el ejemplo del artículo aparecen estos dos fragmentos de código:

// Caso ineficiente (pero típico)
long start = System.currentTimeMillis();
String str = "";
for(int i = 0; i < 10000; i++)
str += i;
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

// Caso eficiente
start = System.currentTimeMillis();
StringBuffer strb = new StringBuffer();
for(int i = 0; i < 10000; i++)
strb.append( i );
System.out.println((System.currentTimeMillis() - start) / 1000.0d);

En el primer fragmento de código, el compilador sustituye el contenido del bucle con un código similar al siguiente:

for (int i=0; i<10000; i++){
    StringBuffer sb = new StringBuffer(str);
    sb.append(i);
    String straux = sb.toString();
    str = sb.toString();
}

A cada iteración se debe ubicar en memoria un nuevo objeto y ese objeto tiene un tamaño cada vez mayor.
La creación dinámica de memoria es una de las operaciones más costosas en Java (y en la mayoría de lenguajes que conozco) y la creación de 10000 instancias de StringBuffer hace que el mismo código resulte mucho más lento.

Ejecutando el código comparativo en mi portátil obtengo 3.277s para ejecutar el bucle con la versión ineficiente y 0.004s en la versión eficiente.

Podéis comprobarlo personalmente copiando y pegando este codigo:

public class Test{
        public static void main(String[] args){
                long start;
                String str;
                StringBuffer strb;

                // Usando el operador "+"
                str = "";
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) str += i;
                System.out.println((System.currentTimeMillis() - start) / 1000.0d); 

                // Usando una instancia de StringBuffer y el método append()
                strb = new StringBuffer();
                start = System.currentTimeMillis();
                for(int i = 0; i < 10000; i++) strb.append(i);
                System.out.println((System.currentTimeMillis() - start) / 1000.0d); 

                // Reroducción de lo que hace el compilador en el caso 1
                str = "";
                start = System.currentTimeMillis();
                for (int i=0; i<10000; i++){
                        StringBuffer sbaux = new StringBuffer();
                        sbaux.append(str);
                        sbaux.append(i);
                        String straux = sbaux.toString();
                        str = straux;
                }
                System.out.println((System.currentTimeMillis() - start) / 1000.0d);
        }
}

Publicado bajo Java | 4 comentarios »

JSR-310 Date and Time aprobado

Publicado el 16 de February de 2007 por Paco

Lo veo en javaHispano y en theServerSide. Parece que por fin se incluirá en la JDK una manera correcta y a la vez cómoda de trabajar con fechas.

La clase GregorianCalendar es extremadamente potente, pero inicializar una instancia correctamente, puede necesitar hasta unas 10 líneas de código. Ni que decir tiene que una aplicación (como la última en la que estoy trabajando) que haga un uso intensivo de fechas y horas así como incrementos y comparaciones sobre los mismos, se puede volver muy pesada.

El hecho de que se vaya o no a incluir una nueva feature en la próxima (o ya veremos cuál) JDK no me preocupa demasiado. Lo que sí que me ha gustado y mucho es el enlace a JodaTime. Una API para trabajar con fechas y horas en Java que tiene cosas tan chulas como esta:

public boolean isAfterPayDay(DateTime datetime) {
  if (datetime.getMonthOfYear() == 2) {
    return datetime.getDayOfMonth() > 26;
  }
  return datetime.getDayOfMonth() > 28;
}

public Days daysToNewYear(LocalDate fromDate) {
  LocalDate newYear = fromDate.plusYears(1).withDayOfYear(1);
  return Days.daysBetween(fromDate, newYear);
}

public boolean isRentalOverdue(DateTime datetimeRented) {
  Period rentalPeriod = new Period().withDays(2).withHours(12);
  return datetimeRented.plus(rentalPeriod).isBeforeNow();
}

public String getBirthMonthText(LocalDate dateOfBirth) {
  return dateOfBirth.monthOfYear().getAsText(Locale.ENGLISH);
}

Si tenéis que programar algo que haga uso de fechas y horas más allá del new Timestamp() os recomiendo que no os perdáis JodaTime.

Por cierto, inauguré hace poco la sección Java. Llevo como 8 años trabajando en Java y JEE y hasta ahora no había escrito prácticamente nada sobre java principalmente por su licencia. Ahora, GPL, me ha animado a publicar alguna que otra cosilla :-)

Si tenéis alguna curiosidad al respecto u os interesa un artículo sobre algún tema pedid y me lo planteo.

Publicado bajo Java, Software | 2 comentarios »

Benchmark Java (JDBC) contra varios gestores de bases de datos

Publicado el 15 de February de 2007 por Paco

Los chicos de devloop se han trabajado un extenso y detallado benchmark de varias bases de datos accedidas desde Java vía JDBC.

Además, han probado con varias VMs y con multitud de casos posibles: tablas llenas, vacías, threads, sin threads, threads con delay…

Los claros vencedores son MySQL y PostgreSQL y no han incluido Oracle porque, según explican, tiene problemas para conseguir una instalación limpia en la Fedora x86-64 que usan.

Llaman la atención algunos casos atípicos y situaciones inexplicables que tienen muy mal rendimiento en general, como por ejemplo que un select count(*) sobre una tabla vacía es más lento que sobre una llena.

También es relevante la diferencia entre el uso de Statement y PreparedStatement y cómo algunos gestores mejoran dramáticamente su rendimiento.
Por último, las mejoras (¡por fin!) de JDBC en la versión 6 de la JDK pasan factura a la hora de evaluar el rendimiento.

De lectura obligatoria si desarrollais usando JDBC ;-)

Publicado bajo Java, Software | 3 comentarios »

Publicidad

Más publicidad :-)

advising investment services best hyip monitoring rating best hyip program best investment firm best investment opportunity best mutual funds classics investment operator reminiscence stock wiley club estate investment real diversified investment essential of investment estate investment property real estate investment real trust extra income fixed income from investment profit uranium us fundamentals of investment gold investment high capital investments high income high profit fund raising high profit margin high yield investments highest financial returns highest fixed rate hyip invest hyip investment hyip monitoring hyip rating income opportunity investment an introduction investment casting investment club investment company investment land investment portfolio investment property investment putnam investment strategy new hyip offshore investment real estate investment club stock investment guide top mutual funds