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.
Top comments (0)