Domanda

Ho una lista di numeri interi, List<Integer> e vorrei convertire tutti gli oggetti interi in Strings, terminando così con un nuovo List<String>.

Naturalmente, potrei crearne uno nuovo List<String> e scorrere l'elenco delle chiamate String.valueOf() per ogni numero intero, ma mi chiedevo se ce ne fosse uno migliore (leggi: più automatico) modo di farlo?

È stato utile?

Soluzione

Per quanto ne so, iterare e istanziare è l'unico modo per farlo.Qualcosa del tipo (per altri potenziale aiuto, poiché sono sicuro che tu sappia come farlo):

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)); 
}

Altri suggerimenti

Utilizzando Raccolte Google dal progetto Guava, potresti usare il file transform metodo nel Elenchi classe

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());

IL List restituito da transform è un visualizzazione sulla backing list: la trasformazione verrà applicata ad ogni accesso alla lista trasformata.

Fai attenzione a Functions.toStringFunction() lancerà a NullPointerException quando applicato a null, quindi usalo solo se sei sicuro che il tuo elenco non conterrà null.

Soluzione per Java 8.Un po' più lungo di quello di Guava, ma almeno non è necessario installare una libreria.

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());

Quello che stai facendo va bene, ma se senti il ​​bisogno di "Java-it-up" potresti usare a Trasformatore e il metodo di raccolta da Apache Commons, per esempio.:

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

..poi..

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

L'origine di String.valueOf mostra questo:

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

Non che abbia molta importanza, ma lo userei toString.

Invece di usare String.valueOf userei .toString();evita alcuni degli autoboxing descritti da @johnathan.holland

Il javadoc dice che valueOf restituisce la stessa cosa di Integer.toString().

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

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

Ecco una soluzione one-liner senza imbrogliare con una libreria non JDK.

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

Un'altra soluzione che utilizza Guava e Java 8

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

Non Java core e non generico, ma la popolare libreria delle raccolte comuni di Jakarta ha alcune astrazioni utili per questo tipo di attività.Nello specifico, dai un'occhiata ai metodi di raccolta su

CollectionUtils

Qualcosa da considerare se stai già utilizzando le raccolte comuni nel tuo progetto.

Per le persone preoccupate per la "boxe" nella risposta di jsight:non c'è nessuno. String.valueOf(Object) viene utilizzato qui e non è necessario eseguire l'unboxing int viene mai eseguito.

Sia che usi Integer.toString() O String.valueOf(Object) dipende da come vuoi gestire eventuali valori nulli.Vuoi lanciare un'eccezione (probabilmente) o avere stringhe "nulle" nel tuo elenco (forse).Se il primo, vuoi lanciare a NullPointerException o qualche altro tipo?

Inoltre, un piccolo difetto nella risposta di jsight: List è un'interfaccia, non puoi usare l'operatore new su di essa.Probabilmente userei a java.util.ArrayList in questo caso, soprattutto perché sappiamo in anticipo quanto sarà lungo l'elenco.

@Jonathan:Potrei sbagliarmi, ma credo che String.valueOf() in questo caso chiamerà la funzione String.valueOf(Object) anziché essere inscatolato in String.valueOf(int).String.valueOf(Object) restituisce semplicemente "null" se è null o chiama Object.toString() se non è null, il che non dovrebbe comportare il boxing (anche se ovviamente è coinvolta la creazione di un'istanza di nuovi oggetti stringa).

Penso che usare Object.toString() per scopi diversi dal debug sia probabilmente una pessima idea, anche se in questo caso i due sono funzionalmente equivalenti (supponendo che l'elenco non abbia valori null).Gli sviluppatori sono liberi di modificare il comportamento di qualsiasi metodo toString() senza alcun preavviso, inclusi i metodi toString() di qualsiasi classe nella libreria standard.

Non preoccuparti nemmeno dei problemi di prestazioni causati dal processo di boxing/unboxing.Se le prestazioni sono critiche, usa semplicemente un array.Se è davvero fondamentale, non utilizzare Java.Cercare di superare in astuzia la JVM porterà solo angoscia.

Una risposta solo per esperti:

    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 permette di farlo in un modo molto semplice e leggibile.Ad esempio, supponendo di avere una lista di Integer e di volerli convertire nella corrispondente rappresentazione String potresti scrivere qualcosa del genere;

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 applica la funzione di conversione solo mentre stai eseguendo l'iterazione del risultato.

Non puoi evitare il "sovraccarico della boxe";I finti contenitori generici di Java possono memorizzare solo oggetti, quindi i tuoi numeri interi devono essere racchiusi in numeri interi.In linea di principio potrebbe evitare il downcast da Object a Integer (poiché è inutile, perché Object è abbastanza buono sia per String.valueOf che per Object.toString) ma non so se il compilatore è abbastanza intelligente da farlo.La conversione da String a Object dovrebbe essere più o meno un'operazione non operativa, quindi non sarei propenso a preoccuparmene.

Solo per divertimento, una soluzione che utilizza il framework fork-join jsr166y che dovrebbe essere presente in 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();

(Disclaimer:Non compilato.Le specifiche non sono definitive.Eccetera.)

È improbabile che sia in JDK7 è un po' di inferenza di tipo e zucchero sintattico per rendere la chiamata withMapping meno dettagliata:

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

Questa è una cosa così semplice da fare che non utilizzerei una libreria esterna (causerebbe una dipendenza nel tuo progetto di cui probabilmente non avrai bisogno).

Abbiamo una classe di metodi statici creati appositamente per svolgere questo tipo di lavori.Poiché il codice è così semplice, lasciamo che Hotspot esegua l'ottimizzazione per noi.Questo sembra essere un tema nel mio codice di recente:scrivi un codice molto semplice (diretto) e lascia che Hotspot faccia la sua magia.Raramente abbiamo problemi di prestazioni con codici come questo: quando arriva una nuova versione della VM, ottieni tutti i vantaggi extra in termini di velocità, ecc.

Per quanto ami le collezioni Jakarta, non supportano i generici e usano 1.4 come display LCD.Sono diffidente nei confronti di Google Collections perché sono elencati come livello di supporto Alpha!

Non ho visto alcuna soluzione che sta seguendo il preside della complessità spaziale.Se l'elenco di numeri interi ha un gran numero di elementi, allora è un grosso 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>.

Possiamo usare iteratore per ottenere lo stesso.

    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();
    }

Volevo solo intervenire con una soluzione orientata agli oggetti al problema.

Se modelli oggetti di dominio, la soluzione è negli oggetti di dominio.Il dominio qui è un elenco di numeri interi per i quali desideriamo valori stringa.

Il modo più semplice sarebbe non convertire affatto l'elenco.

Detto questo, per convertire senza convertire, cambia l'elenco originale di Integer in List of Value, dove Value assomiglia a questo...

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

Questa operazione sarà più veloce e occuperà meno memoria rispetto alla copia dell'elenco.

Buona fortuna!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top