Conversione lista <Integer> in lista <String>


83

Ho una lista di numeri interi, List<Integer> e mi piacerebbe convertire tutti gli oggetti interi in stringhe, finendo così con un nuovo List<String>.

Naturalmente, ho potuto creare un nuovo ciclo List<String> e attraverso la lista chiamando String.valueOf() per ogni intero, ma mi chiedevo se ci fosse una migliore (leggi: più automatico) modo di farlo?

64

Per quanto ne so, l'iterazione e l'istanza sono l'unico modo per farlo. Qualcosa di simile (per gli altri potenziali di aiuto, dal momento che sono sicuro di sapere come fare):

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

Quando è semplice, questo si chiama bellezza. 07 set. 122012-09-07 16:11:02

+1

Il poster originale sembrava indicare che ci aveva pensato, ma considerava questa soluzione troppo complessa o noiosa. Ma ho difficoltà a immaginare cosa potrebbe essere più facile. Sì, a volte devi scrivere 3 o 4 righe di codice per fare un lavoro. 07 set. 122012-09-07 17:44:35

  0

Ma questo ti lega a ArrayList. Questo può essere fatto usando la stessa implementazione dell'elenco originale? 10 apr. 132013-04-10 10:23:40

  0

@Andreas oldList.getClass(). NewInstance() farà 09 mag. 132013-05-09 16:56:18


2

@ Jonathan: Potrei sbagliarmi, ma credo che String.valueOf() in questo caso chiamerà la funzione String.valueOf (Object) anziché essere racchiusa in String.valueOf (int). String.valueOf (Object) restituisce semplicemente "null" se è null o chiama Object.toString() se non-null, che non dovrebbe coinvolgere il pugilato (anche se ovviamente l'istanziazione di nuovi oggetti stringa è implicata).


9

Invece di utilizzare String.valueOf vorrei utilizzare .toString(); evita parte del boxing automatico descritto da @ johnathan.holland

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

come indicato da Tom Hawtin nella risposta "vincente", non è possibile l'Elenco di istanze <String> in quanto è solo un'interfaccia. 14 set. 082008-09-14 23:11:45

  0

Heh lo sapevo. Ho solo scritto il codice senza provarlo. Lo aggiusterò nella mia risposta. 15 set. 082008-09-15 18:24:42


2

Penso che utilizzando Object.toString() per scopi diversi da quelli di debug è probabilmente una pessima idea, anche se in questo caso i due sono funzionalmente equivalenti (assumendo che la lista non ha valori null). Gli sviluppatori sono liberi di modificare il comportamento di qualsiasi metodo toString() senza alcun avviso, inclusi i metodi toString() di qualsiasi classe nella libreria standard.

Non preoccupatevi nemmeno dei problemi di prestazioni causati dal processo di boxing/unboxing. Se le prestazioni sono critiche, basta usare un array. Se è veramente critico, non usare Java. Cercare di superare in astuzia la JVM porterà solo ad angoscia.

  0

+1 per "heartache" ... 07 mar. 102010-03-07 13:06:18


9

La fonte per String.valueOf mostra questo:

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

Non che sia importante tanto, ma vorrei usare toString.


1

Non è possibile evitare il "sovraccarico di boxe"; I contenitori generici fasulli di Java possono solo memorizzare oggetti, quindi i tuoi interi devono essere racchiusi in 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 per farlo. La conversione da String a Object dovrebbe essere più o meno un no-op, quindi non sarei incline a preoccuparsi di quello.

  0

il compilatore NON è abbastanza intelligente per farlo. Quando javac viene eseguito, in realtà elimina tutte le informazioni di tipo generico. L'implementazione sottostante di una raccolta di generici SEMPRE memorizza riferimenti di oggetti. È possibile omettere la parametrizzazione <T> e ottenere un tipo "raw". "Lista l = nuova lista()" contro "Lista <String> l = nuova lista <String>()".ovviamente, questo significa che "Lista <String> l = (Lista <String>) nuova Lista <Integer>()" verrà effettivamente compilata ed eseguita, ma è, ovviamente, molto pericolosa. 04 giu. 112011-06-04 20:20:45


3

Non core Java e non generico, ma la libreria di raccolte comuni di Jakarta ha alcune utili astrazioni per questo tipo di attività. In particolare, hanno uno sguardo ai metodi di raccogliere su

CollectionUtils

Qualcosa da prendere in considerazione se si sta già utilizzando collezioni Commons nel progetto.

+4

Non utilizzare mai raccolte Apache. Sono vecchi, obsoleti, non sicuri del testo e scritti male. 07 mar. 102010-03-07 12:51:58


39

Quello che stai facendo va bene, ma se si sente il bisogno 'Java-it-up' che si potrebbe utilizzare per un Transformer e il collect method da Apache Commons, per esempio:

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

..e poi ..

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

wow, cose interessanti! 10 dic. 092009-12-10 00:06:03

+1

CollectionUtils.collect (collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer()); Tuttavia, StringValueTransformer utilizza String.valueOf ... 17 feb. 102010-02-17 14:12:57

+5

A meno che non sia stato fatto nuovo lavoro sulle raccolte di apache, non generano generici. 07 mar. 102010-03-07 12:50:48

+1

Questo è davvero Java-ing-down. Questo non è un idioma Java, e più simile alla programmazione funzionale. Forse quando avremo delle chiusure in Java 8, potresti chiamarlo Java idiomatico. 07 gen. 122012-01-07 22:44:38

  0

Sicuramente vuoi utilizzare Collections4 per questo (non le vecchie collezioni 3.x) per il supporto dei generici: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils .html # transform% 28java.util.Collection,% 20org.apache.commons.collections4.Transformer% 29 06 gen. 162016-01-06 10:17:47

  0

Definire una nuova classe solo per essere "più OOP o idiomatica" ... Non vedo come sia meglio di il semplice ciclo per ogni ciclo. Richiede più codice e sposta la funzionalità (che potrebbe essere mitigata da classi anonime, ma comunque). Questo stile funzionale inizia a diventare utile solo quando esiste una sintassi decente (ad esempio espressioni lambda da Java 8), come i linguaggi funzionali l'hanno fornita per decenni. 31 gen. 162016-01-31 21:02:34


3

alle persone interessate di "boxe" in risposta di jsight: non c'è nessuno. String.valueOf(Object) viene utilizzato qui e non viene mai eseguito un annullamento del pacchetto su int.

Se si utilizza Integer.toString() o String.valueOf(Object) dipende da come si desidera gestire possibili valori nulli. Vuoi lanciare un'eccezione (probabilmente), o avere stringhe "null" nella tua lista (forse). Se il primo, vuoi lanciare un NullPointerException o qualche altro tipo?

Inoltre, un piccolo difetto nella risposta di jsight: List è un'interfaccia, non è possibile utilizzare il nuovo operatore su di esso. Probabilmente userò uno java.util.ArrayList in questo caso, soprattutto perché sappiamo in anticipo per quanto tempo l'elenco è probabile che sia.


2

una risposta per soli 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); 
  0

Questo funziona ma a scapito dell'inefficienza. Le stringhe Java sono due byte per carattere, quindi "," aggiunge un costo fisso di quattro byte per intero prima di contare il numero intero stesso .... tra le altre cose. 13 ott. 102010-10-13 21:59:41

  0

Penso che la regex potrebbe essere più un problema in termini di efficienza del ciclo della CPU grezza. In termini di memoria, immagino che un'implementazione ragionevole (assumendo l'implementazione irragionevole di "String" di Sun) condivida lo stesso backing array (da 'all'), quindi sarà davvero abbastanza efficiente in memoria, che sarebbe importante per prestazioni a lungo termine. A meno che tu non voglia mantenere solo uno degli elementi ... 13 ott. 102010-10-13 22:12:16


0

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

(Esonero di responsabilità:.. Non compilato Spec non è finalizzato Ecc)

Difficilmente essere in JDK7 è un po 'di inferenza di tipo sintattico e lo zucchero a fare quella chiamata withMapping meno prolissa:

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

0

Questa è una cosa fondamentale da fare Non utilizzerei una libreria esterna (causerà una dipendenza nel progetto che probabilmente non è necessaria).

Abbiamo una classe di metodi statici creati appositamente per svolgere questo tipo di lavoro. Poiché il codice per questo è così semplice, Hotspot fa l'ottimizzazione per noi. Questo sembra essere un tema nel mio codice di recente: scrivere codice molto semplice (semplice) e lasciare che Hotspot faccia la sua magia. Abbiamo raramente hanno problemi di prestazioni in tutto il codice come questo - quando una nuova versione VM arriva si ottengono tutti i vantaggi di velocità in più ecc

Per quanto io amo collezioni Giacarta, non supportano Generics e utilizzare 1,4 come il display LCD . Sono diffidente nei confronti delle raccolte Google perché sono elencate come livello di supporto Alpha!


82

Utilizzando Google Collections from Guava-Project, è possibile utilizzare il metodo transform nella classe Lists

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 è una vista nella lista supporto - la trasformazione sarà applicato su ogni accesso al trasformata elenco.

Si noti che Functions.toStringFunction() genererà uno NullPointerException quando viene applicato a null, quindi utilizzarlo solo se si è certi che l'elenco non conterrà nulla.

+1

Sarebbe bello se ci fossero più funzioni pronte accanto a Functions.toStringFunction() 07 set. 102010-09-07 06:58:21

+1

pulito ma forse non così veloce .. 1 chiamata di funzione extra per valore? 09 dic. 102010-12-09 15:35:27

+3

HotSpot può effettuare chiamate di funzione in linea, quindi se è chiamato abbastanza, non dovrebbe fare la differenza. 09 dic. 102010-12-09 20:45:53

+3

Non lo sottovaluta perché è davvero una soluzione. Ma incoraggiare le persone ad aggiungere una dipendenza dalla biblioteca per risolvere un compito così semplice è per me un no-go. 28 feb. 142014-02-28 19:09:08

+1

Bella soluzione se stai già utilizzando Guava nella nostra soluzione. 28 apr. 152015-04-28 12:46:16

+1

Un potenziale problema è che la trasformazione viene applicata pigramente (potenzialmente molte volte). Potresti voler restituire 'new ArrayList <> (Lists.transform (interi, Functions.toStringFunction()))' invece di evitare questo, 06 gen. 162016-01-06 10:13:23

  0

L'inverso se ti sei imbattuto in questa domanda alla ricerca di String -> Numero: 'Lists.transform (listOfStrings, Ints.stringConverter()); ' 17 feb. 162016-02-17 22:21:55


2

Lambdaj consente di farlo in un modo molto semplice e leggibile.Ad esempio, supponendo di avere una lista di Integer e di convertirli nella rappresentazione String corrispondente, 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 si sta iterando sul risultato.


8

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

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

+1 per puro gusto hackishness. 10 mar. 132013-03-10 19:30:46


-1

Volevo solo inserire una soluzione orientata agli oggetti al problema.

Se si modellano oggetti di dominio, la soluzione si trova negli oggetti dominio. Il dominio qui è un elenco di numeri interi per i quali vogliamo valori stringa.

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

Detto questo, al fine di convertire senza convertire, modificare l'elenco originale di Integer la lista valore, dove il valore simile a questa ...

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

Questo sarà più veloce e occupano meno memoria che copiare la lista.

Buona fortuna!


52

Soluzione per Java 8. Un po 'più lungo 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()); 
  0

Mentre questo è un po 'più lungo per l'esempio di 'toString', finisce per essere più breve per le conversioni non supportate dalla libreria delle funzioni di Guava. Le funzioni personalizzate sono ancora facili, ma è significativamente più codice di questo flusso Java 8 24 ott. 172017-10-24 20:17:53


5

un'altra soluzione utilizzando Guava e Java 8

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

0

Non ho visto alcuna soluzione che sta seguendo il principio di spazio complessità. Se l'elenco di numeri interi ha un numero elevato di elementi, allora è il grande problema di .

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