This content originally appeared on DEV Community and was authored by Gabriel Menezes da Silva
Contexto
Trabalhei em um aplicativo mobile nativo para Android utilizado por uma empresa de logística. Esse app é usado por operadores para escanear etiquetas de pacotes e contêineres, a fim de realizar as etapas necessárias no sistema para classificá-los e ordená-los.
Existe uma função responsável por receber a string, manipulá-las e enviar para o back-end a string correta para que ela seja processada.
Essa função é o coração de todo o aplicativo — sem ela, o processo logístico não funcionaria. Portanto, qualquer melhoria nela é sempre muito bem-vinda.
Neste artigo, será explicado quais melhorias foram feitas e os motivos por trás da implementação.
Qual foi a melhoria feita?
Uma operação executada inúmeras vezes dentro dessa função é a concatenação de strings.
Você pode estar se perguntando: por que melhorar a concatenação é importante?
Dependendo de como ela é feita, você literalmente pode ter problemas de desempenho e uso excessivo de memória para obter o resultado final.
O problema
Antes da melhoria, a concatenação das strings era feita da seguinte forma, usando o famoso operador +=, muito comum no dia a dia dos programadores Kotlin:
var result = ""
val iterations = 1000
for (i in 0 until iterations) {
result += "Item $i "
}
Ok, mas qual é o problema de usar o +=?
- A classe String é imutável, ou seja, a cada iteração uma nova instância de String é criada, e mais memória é alocada.
Em outras palavras, quanto maior o número de iterações, mais memória é usada e mais tempo é necessário para obter o resultado final!
A solução
Usar o StringBuilder em vez do operador +=.
Os motivos são simples:
- 1. StringBuilder é mutável, ou seja, nenhuma nova instância de string é criada a cada iteração.
- 2. A mesma alocação de memória é usada durante todo o processo de concatenação.
O código ficaria da seguinte forma:
val result = buildString {
for (i in 0 until iterations) {
append("Item $i ")
}
}
A função buildString utiliza internamente o StringBuilder.
Para referência, veja a documentação oficial do Kotlin.
Exemplo prático
import kotlin.system.measureTimeMillis
fun main() {
val iterations = 1000
// Usando +=
val timePlusEqual = measureTimeMillis {
var result = ""
for (i in 0 until iterations) {
result += "Item $i "
}
}
// Usando buildString (internamente usa StringBuilder)
val timeBuildString = measureTimeMillis {
val result = buildString {
for (i in 0 until iterations) {
append("Item $i ")
}
}
}
println("Tempo com +=: ${timePlusEqual}ms")
println("Tempo com buildString: ${timeBuildString}ms")
}
E o resultado será uma grande diferença:
Tempo com +=: 21ms
Tempo com buildString: 0ms
Neste artigo foi mostrado apenas um exemplo simples, mas imagine isso em larga escala, com strings enormes — o tempo de execução e o consumo de memória aumentariam consideravelmente.
Conclusão
Muitas vezes pensamos que, para causar um grande impacto em um projeto, é preciso fazer algo gigantesco — como mudar toda a arquitetura do aplicativo.
Mas isso não é verdade.
Pequenas melhorias podem gerar um impacto enorme e entregar valor real aos clientes.
Ter isso em mente traz uma sensação de conforto: saber que otimizações simples também fazem a diferença.
This content originally appeared on DEV Community and was authored by Gabriel Menezes da Silva