Pergunta

Eu tenho uma lista de números inteiros, List<Integer> e gostaria de converter todos os objetos inteiros em Strings, finalizando assim com um novo List<String>.

Naturalmente, eu poderia criar um novo List<String> e percorrer a lista chamando String.valueOf() para cada número inteiro, mas eu queria saber se havia um melhor (leia: mais automático) maneira de fazer isso?

Foi útil?

Solução

Pelo que eu sei, iterar e instanciar é a única maneira de fazer isso.Algo como (para outros possíveis ajuda, já que tenho certeza que você sabe como fazer isso):

List<Integer> oldList = ...
/* Specify the size of the list up front to prevent resizing. */
List<String> newList = new ArrayList<String>(oldList.size()) 
for (Integer myInt : oldList) { 
  newList.add(String.valueOf(myInt)); 
}

Outras dicas

Usando Coleções do Google do Guava-Project, você poderia usar o transform método no Listas aula

import com.google.common.collect.Lists;
import com.google.common.base.Functions

List<Integer> integers = Arrays.asList(1, 2, 3, 4);

List<String> strings = Lists.transform(integers, Functions.toStringFunction());

O List retornado por transform é um visualizar na lista de apoio - a transformação será aplicada em cada acesso à lista transformada.

Esteja ciente que Functions.toStringFunction() vai lançar um NullPointerException quando aplicado a nulo, use-o apenas se tiver certeza de que sua lista não conterá nulo.

Solução para Java 8.Um pouco mais longo que o Guava, mas pelo menos não é necessário instalar biblioteca.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

//...

List<Integer> integers = Arrays.asList(1, 2, 3, 4);
List<String> strings = integers.stream().map(Object::toString)
                                        .collect(Collectors.toList());

O que você está fazendo é bom, mas se sentir necessidade de 'Java-it-up', você pode usar um Transformador e a método de coleta de Apache Commons, por exemplo.:

public class IntegerToStringTransformer implements Transformer<Integer, String> {
   public String transform(final Integer i) {
      return (i == null ? null : i.toString());
   }
}

..e então..

CollectionUtils.collect(
   collectionOfIntegers, 
   new IntegerToStringTransformer(), 
   newCollectionOfStrings);

A fonte de String.valueOf mostra isso:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

Não que isso importe muito, mas eu usaria toString.

Em vez de usar String.valueOf eu usaria .toString();evita parte do boxe automático descrito por @johnathan.holland

O javadoc diz que valueOf retorna a mesma coisa que Integer.toString().

List<Integer> oldList = ...
List<String> newList = new ArrayList<String>(oldList.size());

for (Integer myInt : oldList) { 
  newList.add(myInt.toString()); 
}

Aqui está uma solução simples, sem trapaça, com uma biblioteca não JDK.

List<String> strings = Arrays.asList(list.toString().replaceAll("\\[(.*)\\]", "$1").split(", "));

Outra solução usando Guava e Java 8

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<String> strings = Lists.transform(numbers, number -> String.valueOf(number));

Não é o Java principal e não é genérico, mas a popular biblioteca de coleções comuns de Jacarta tem algumas abstrações úteis para esse tipo de tarefa.Especificamente, dê uma olhada nos métodos de coleta em

ColeçãoUtils

Algo a considerar se você já estiver usando coleções comuns em seu projeto.

Para as pessoas preocupadas com o "boxe" na resposta do jsight:não há nenhum. String.valueOf(Object) é usado aqui, e não há unboxing para int é sempre realizado.

Quer você use Integer.toString() ou String.valueOf(Object) depende de como você deseja lidar com possíveis nulos.Você deseja lançar uma exceção (provavelmente) ou ter Strings "nulas" em sua lista (talvez).Se for o primeiro, você quer jogar um NullPointerException ou algum outro tipo?

Além disso, uma pequena falha na resposta do jsight: List é uma interface, você não pode usar o operador new nela.Eu provavelmente usaria um java.util.ArrayList neste caso, especialmente porque sabemos antecipadamente qual será o tamanho provável da lista.

@Jonathan:Posso estar enganado, mas acredito que String.valueOf() neste caso chamará a função String.valueOf(Object) em vez de ser encaixotado em String.valueOf(int).String.valueOf(Object) apenas retorna "null" se for nulo ou chama Object.toString() se não for nulo, o que não deve envolver boxe (embora obviamente esteja envolvido a instanciação de novos objetos de string).

Acho que usar Object.toString() para qualquer finalidade diferente de depuração é provavelmente uma péssima ideia, embora neste caso os dois sejam funcionalmente equivalentes (assumindo que a lista não tenha nulos).Os desenvolvedores são livres para alterar o comportamento de qualquer método toString() sem qualquer aviso, incluindo os métodos toString() de qualquer classe na biblioteca padrão.

Nem se preocupe com os problemas de desempenho causados ​​pelo processo de boxing/unboxing.Se o desempenho for crítico, basta usar um array.Se for realmente crítico, não use Java.Tentar ser mais esperto que a JVM só causará dor de cabeça.

Uma resposta apenas para especialistas:

    List<Integer> ints = ...;
    String all = new ArrayList<Integer>(ints).toString();
    String[] split = all.substring(1, all.length()-1).split(", ");
    List<String> strs = Arrays.asList(split);

Lambdaj permite fazer isso de uma forma muito simples e legível.Por exemplo, supondo que você tenha uma lista de números inteiros e queira convertê-los na representação String correspondente, você poderia escrever algo assim;

List<Integer> ints = asList(1, 2, 3, 4);
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> {
    public String convert(Integer i) { return Integer.toString(i); }
}

Lambdaj aplica a função de conversão apenas enquanto você itera no resultado.

Você não pode evitar a “sobrecarga do boxe”;Os contêineres genéricos falsos do Java só podem armazenar objetos, portanto, seus ints devem ser colocados em números inteiros.Em princípio, isso poderia evitar o downcast de Object para Integer (já que é inútil, porque Object é bom o suficiente para String.valueOf e Object.toString), mas não sei se o compilador é inteligente o suficiente para fazer isso.A conversão de String para Object deve ser mais ou menos autônoma, então eu não estaria disposto a me preocupar com isso.

Apenas por diversão, uma solução usando o framework jsr166y fork-join que deveria estar no JDK7.

import java.util.concurrent.forkjoin.*;

private final ForkJoinExecutor executor = new ForkJoinPool();
...
List<Integer> ints = ...;
List<String> strs =
    ParallelArray.create(ints.size(), Integer.class, executor)
    .withMapping(new Ops.Op<Integer,String>() { public String op(Integer i) {
        return String.valueOf(i);
    }})
    .all()
    .asList();

(Isenção de responsabilidade:Não compilado.As especificações não estão finalizadas.Etc.)

É improvável que esteja no JDK7 um pouco de inferência de tipo e açúcar sintático para tornar a chamada withMapping menos detalhada:

    .withMapping(#(Integer i) String.valueOf(i))

Isso é algo tão básico que eu não usaria uma biblioteca externa (isso causará uma dependência em seu projeto que você provavelmente não precisa).

Temos uma classe de métodos estáticos criados especificamente para realizar esse tipo de trabalho.Como o código para isso é tão simples, deixamos o Hotspot fazer a otimização para nós.Este parece ser um tema no meu código recentemente:escreva um código muito simples (direto) e deixe o Hotspot fazer sua mágica.Raramente temos problemas de desempenho em torno de códigos como este - quando surge uma nova versão da VM, você obtém todos os benefícios extras de velocidade, etc.

Por mais que eu ame as coleções de Jacarta, elas não suportam Genéricos e usam 1.4 como LCD.Desconfio das Coleções do Google porque elas estão listadas no nível de suporte Alfa!

Não vi nenhuma solução que esteja seguindo o principal da complexidade espacial.Se a lista de números inteiros tiver um grande número de elementos, é um grande problema.

It will be really good to remove the integer from the List<Integer> and free
the space, once it's added to List<String>.

Podemos usar o iterador para conseguir o mesmo.

    List<Integer> oldList = new ArrayList<>();
    oldList.add(12);
    oldList.add(14);
    .......
    .......

    List<String> newList = new ArrayList<String>(oldList.size());
    Iterator<Integer> itr = oldList.iterator();
    while(itr.hasNext()){
        newList.add(itr.next().toString());
        itr.remove();
    }

Eu só queria apresentar uma solução orientada a objetos para o problema.

Se você modelar objetos de domínio, a solução estará nos objetos de domínio.O domínio aqui é uma lista de inteiros para os quais queremos valores de string.

A maneira mais fácil seria não converter a lista.

Dito isto, para converter sem converter, altere a lista original de Inteiros para Lista de Valores, onde Valor se parece com isto...

class Value {
    Integer value;
    public Integer getInt()
    {
       return value;
    }
    public String getString()
    {
       return String.valueOf(value);
    }
}

Isso será mais rápido e ocupará menos memória do que copiar a Lista.

Boa sorte!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top