Como obter o índice atual em forEach Kotlin: do iniciante ao profissional
\n\nImagine: você está programando em Kotlin, processando uma lista de usuários, e de repente percebe que precisa não apenas do elemento, mas também da sua posição na coleção. Instintivamente, você recorre ao antiquado for (i in 0 until list.size)… Pare! Em Kotlin existem formas mais elegantes e eficientes. Neste artigo, vamos analisar como obter o índice atual em forEach Kotlin, comparar o desempenho de diferentes abordagens e escolher a melhor para o seu projeto. Isto não é apenas uma tradução da documentação — é o resultado de medições reais e da experiência da comunidade Stack Overflow.
Por que forEach sem índice é um problema?
\n\nO list.forEach { item -> ... } padrão é conveniente, mas quando você precisa saber a posição do elemento, muitos escrevem gambiarras:
var index = 0\nlist.forEach { item ->\n println("$index: $item")\n index++\n}\n\nIsso funciona, mas parece complicado e propenso a erros (esqueceu o incremento? tem um bug). Além disso, uma variável mutável fora do loop é uma violação do estilo funcional e um problema potencial em cenários multithread. Vamos ver as soluções corretas.
\n\nMétodo 1: Usando withIndex() — simples e elegante
\n\nA resposta mais popular no Stack Overflow é a função withIndex(). Ela retorna uma sequência de pares IndexedValue, onde cada elemento tem os campos index e value.
val list = listOf("Kotlin", "Java", "Python")\nlist.withIndex().forEach { (index, value) ->\n println("Elemento #$index: $value")\n}\n\nO que está acontecendo aqui? withIndex() cria uma sequência lazy, que envolve cada elemento em um objeto IndexedValue. A desestruturação (index, value) torna o código limpo e legível.
Vantagens:
\n- \n
- Concisão — uma linha em vez de três \n
- Lazy — não cria coleções extras na memória \n
- Legibilidade — fica claro imediatamente que estamos trabalhando com índice \n
Desvantagens:
\n- \n
- Pequeno overhead na criação do wrapper
IndexedValue(embora em 99% dos casos seja imperceptível) \n
Método 2: forEachIndexed — alternativa nativa
\n\nKotlin fornece a função pronta forEachIndexed, que aceita uma lambda com dois parâmetros: índice e valor.
list.forEachIndexed { index, value ->\n println("Posição $index: $value")\n}\n\nIsso é praticamente o mesmo que withIndex().forEach, mas sem uma chamada extra. A implementação interna de forEachIndexed também usa IndexedValue? Não, ela passa o índice diretamente, o que é um pouco mais rápido.
Vantagens:
\n- \n
- Escrita mais curta possível \n
- Sem criação de objetos intermediários \n
- Idiomático para Kotlin \n
Desvantagens:
\n- \n
- Menos flexível que
withIndex()— não pode ser combinado com outros operadores de encadeamento (ex:filterantes deforEach) \n
Método 3: filterIndexed — quando você precisa filtrar por índice
\n\nSe você precisa não apenas obter o índice, mas também filtrar elementos pela sua posição, filterIndexed é a sua escolha.
val list = listOf("a", "b", "c", "d", "e")\nval evenIndexed = list.filterIndexed { index, _ -> index % 2 == 0 }\nprintln(evenIndexed) // [a, c, e]\n\nObserve: o segundo parâmetro é o próprio elemento, mas nós o ignoramos usando _. Esta é uma prática padrão em Kotlin para variáveis não utilizadas.
Vantagens:
\n- \n
- Flexibilidade — pode combinar filtragem e transformação \n
- Estilo funcional puro \n
Des