Introdução: por que este tópico é tão popular?
\n\nSe você já programou em Rust, certamente já se deparou com a situação em que tem um Vec<char> e precisa obter uma string comum String. No Stack Overflow, esta pergunta acumulou milhares de visualizações e dezenas de respostas — e não é por acaso.
Em Rust, trabalhar com strings é uma arte à parte. Diferente de muitas linguagens onde strings são apenas arrays de caracteres, aqui temos String (mutável, dona da string) e &str (referência a uma fatia de string). E Vec<char> é um vetor de caracteres Unicode de quatro bytes. Portanto, simplesmente "juntá-los", como em Python ou JavaScript, não funciona.
Neste artigo, vamos abordar 4 maneiras funcionais de converter Vec<char> em String, discutir desempenho, erros típicos de iniciantes e fornecer exemplos de código prontos. Vamos lá!
1. A maneira mais simples: iter().collect()
\n\nEste método é um clássico do Rust. Se você já conhece iteradores, sabe que collect() pode reunir praticamente qualquer coleção. Para strings, fica assim:
fn main() {\n let chars: Vec<char> = vec!['O', 'l', 'á'];\n let s: String = chars.iter().collect();\n println!("{}", s); // Exibe: Olá\n}\n\nAqui, iter() retorna um iterador sobre referências aos caracteres (&char), e collect() os reúne em uma String. O compilador Rust entende automaticamente que precisa implementar a trait FromIterator para String.
Importante: se você escrever chars.into_iter().collect(), obterá o mesmo resultado, mas o vetor será consumido. Escolha a variante dependendo se você precisa do vetor original posteriormente.
Prós e contras
\n- \n
- ✅ Mínimo de código, legível \n
- ✅ Funciona com qualquer iterador de caracteres \n
- ❌ Um pouco mais lento que métodos especializados (mas para 99% dos casos a diferença é imperceptível) \n
2. Montagem via String::from_iter()
\n\nEsta maneira é, essencialmente, a mesma coisa que collect(), mas de forma explícita. Às vezes é mais conveniente para legibilidade:
use std::iter::FromIterator;\n\nfn main() {\n let chars: Vec<char> = vec!['R', 'u', 's', 't'];\n let s = String::from_iter(chars);\n println!("{}", s); // Rust\n}\n\nObserve: eu passei chars diretamente, e não chars.iter(). Isso funciona porque Vec<char> implementa IntoIterator. Se você precisar manter o vetor intacto, use String::from_iter(chars.iter()).
Pessoalmente, prefiro esta opção quando o código é lido por iniciantes — o nome explícito da função from_iter deixa claro imediatamente o que está acontecendo.
3. Iteração manual com push()
\n\nÀs vezes é necessário mais controle. Por exemplo, você pode querer adicionar um prefixo ou filtrar parte dos caracteres. Nesse caso, pode fazer assim:
\n\nfn main() {\n let chars: Vec<char> = vec!['O', 'l', 'á'];\n let mut s = String::with_capacity(chars.len());\n \n for c in chars {\n s.push(c);\n }\n \n println!("{}", s); // Olá\n}\n\nUsei String::with_capacity() para alocar memória antecipadamente — isso acelera o processo, pois evita realocações desnecessárias durante o push().
Quando isso é necessário?
\n- \n
- Quando você está fazendo outras manipulações na string simultaneamente \n
- Quando deseja adicionar separadores ou alterar maiúsculas/minúsculas em tempo real \n
- Para aprendizado — para entender como as strings funcionam "por baixo dos panos" \n
O desempenho deste método é praticamente idêntico ao collect(), se você