Преобразование списка <Integer> в список <String>


83

У меня есть список целых чисел, List<Integer> и я хотел бы, чтобы преобразовать все объекты в целое число строк, таким образом заканчивал с новым List<String>.

Естественно, я мог бы создать новую List<String> и цикл по списку вызывающего String.valueOf() для каждого целого числа, но мне было интересно, если там было лучше (читай: более автоматизированным) способ сделать это?

64

Насколько я знаю, итерация и создание экземпляров - единственный способ сделать это. Нечто подобное (для других потенциал помощи, так как я уверен, что вы знаете, как это сделать):

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

Когда это просто, это называется красотой. 07 сен. 122012-09-07 16:11:02

+1

Оригинальный плакат, казалось, указывал, что он думал об этом, но считал это решение слишком сложным или утомительным. Но мне трудно представить, что может быть проще. Да, иногда вам нужно написать 3 или 4 строки кода, чтобы выполнить работу. 07 сен. 122012-09-07 17:44:35

  0

Но это связывает вас с ArrayList. Можно ли это сделать, используя ту же реализацию, что и исходный список? 10 апр. 132013-04-10 10:23:40

  0

@Andreas oldList.getClass(). NewInstance() будет делать 09 май. 132013-05-09 16:56:18


2

@ Джонатан: Я могу ошибаться, но я считаю, что String.valueOf() в этом случае будет называть функцию String.valueOf (Object) вместо того, чтобы вставлять в поле String.valueOf (int). String.valueOf (Object) просто возвращает «null», если он имеет значение null, или вызывает Object.toString(), если не null, который не должен включать в себя бокс (хотя подразумевается создание экземпляров новых строковых объектов).


9

Вместо использования String.valueOf я бы использовал .toString(); он избегает некоторых ботов в авто, описанных @ johnathan.holland

Javadoc говорит, что valueOf возвращает то же, что и Integer.toString().

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

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

как указано Томом Хоутином в ответе «выигрыш», нельзя привести список <String>, поскольку это только интерфейс. 14 сен. 082008-09-14 23:11:45

  0

Хех я знал это. Просто я написал код, не пробовав его. Я исправлю это в своем ответе. 15 сен. 082008-09-15 18:24:42


2

Я думаю, с помощью Object.toString() для любых целей, кроме отладки, вероятно, очень плохая идея, даже если в этом случае два функционально эквивалентны (предполагается, что список не имеет аннулирует). Разработчики могут свободно изменять поведение любого метода toString() без предупреждения, включая методы toString() любых классов в стандартной библиотеке.

Не беспокойтесь о проблемах с производительностью, вызванных процессом бокса/распаковки. Если производительность критическая, просто используйте массив. Если это действительно важно, не используйте Java. Попытка перехитрить JVM приведет только к душевной боли.

  0

+1 для «heartache» ... 07 мар. 102010-03-07 13:06:18


9

Источником String.valueOf показывает это:

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

Не так уж важно много, но я хотел бы использовать ToString.


1

Вы не можете избежать «боксерских накладных расходов»; Явные универсальные контейнеры Java могут хранить только объекты, поэтому ваши int должны быть помещены в целые числа. В принципе, это могло бы избежать опускания от Object до Integer (поскольку это бессмысленно, потому что Object достаточно хорош как для String.valueOf, так и для Object.toString), но я не знаю, достаточно ли достаточно компилятора для этого. Преобразование из String в Object должно быть более или менее не-op, поэтому я бы не стал беспокоиться об этом.

  0

компилятор НЕ достаточно умный, чтобы сделать это. Когда javac запускается, на самом деле он удаляет всю информацию типа generics. Основная реализация коллекции генериков ALWAYS хранит ссылки на объекты. Фактически вы можете опустить параметр <T> и получить «сырой» тип. "Список l = новый список()" по сравнению с "Список <String> l = новый Список <String>()".конечно, это означает, что «Список <String> l = (Список <String>) новый список <Integer>()« будет фактически скомпилирован и запущен, но, очевидно, очень опасен. 04 июн. 112011-06-04 20:20:45


3

Не ядро ​​Java, а не общепринятое, но популярная библиотека коллекций коллективных коллекций Джакарт имеет некоторые полезные абстракции для такого рода задач. В частности, взглянуть на сборных методах на

CollectionUtils

Что-то рассмотреть, если вы уже используете Общины коллекцию в вашем проекте.

+4

Никогда не используйте коллекции Apache. Они старые, устаревшие, не безопасные и плохо написанные. 07 мар. 102010-03-07 12:51:58


39

Что вы делаете это хорошо, но если вы чувствуете необходимость «Java-он-вверх» вы можете использовать Transformer и collect method от Apache Commons, например:

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

..и тогда ..

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

ничего себе, классный материал! 10 дек. 092009-12-10 00:06:03

+1

CollectionUtils.collect (collectionOfIntegers, новый org.apache.commons.collections.functors.StringValueTransformer()); Но, StringValueTransformer использует String.valueOf ... 17 фев. 102010-02-17 14:12:57

+5

Если в коллекциях apache не было сделано никаких новых работ, они не генерируют дженерики. 07 мар. 102010-03-07 12:50:48

+1

Это действительно Java-ing-it. Это не идиоматическая Java, а скорее функциональное программирование. Может быть, когда мы закроем Java 8, вы можете назвать это идиоматической Java. 07 янв. 122012-01-07 22:44:38

  0

Вы определенно хотите использовать Collections4 для этого (а не для старых коллекций 3.x) для поддержки дженериков: 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 янв. 162016-01-06 10:17:47

  0

Определение нового класса только для того, чтобы быть «больше ООП или идиоматическим» ... Я не вижу, как это лучше, чем простой для каждого цикла. Это требует большего количества кода и отталкивает функциональность (что может быть смягчено анонимными классами, но все же). Этот функциональный стиль начинает становиться полезным, когда есть приличный синтаксис (т. Е. Лямбда-выражения с Java 8), как и функциональные языки, предоставляемые на протяжении десятилетий. 31 янв. 162016-01-31 21:02:34


3

Для людей, обеспокоенных "бокс" в ответ jsight в: там нет. Здесь используется String.valueOf(Object), и никакой разборки до int не выполняется.

Используете ли вы Integer.toString() или String.valueOf(Object), зависит от того, как вы хотите обрабатывать возможные значения нуля. Вы хотите выбросить исключение (возможно) или иметь «нулевые» строки в своем списке (возможно). Если первый, вы хотите бросить NullPointerException или какой-нибудь другой тип?

Кроме того, один небольшой недостаток в ответе jsight: List - это интерфейс, вы не можете использовать на нем новый оператор. Я бы, вероятно, использовал java.util.ArrayList в этом случае, тем более, что мы знаем, как долго этот список, вероятно, будет.


2

Ответ только для специалистов:

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

Это работает, но за счет неэффективности. Строки Java - это два байта на символ, поэтому «,» добавляет фиксированную стоимость в четыре байта на целое число, прежде чем считать самое целое ... среди прочего. 13 окт. 102010-10-13 21:59:41

  0

Я думаю, что регулярное выражение может быть более проблематичным с точки зрения эффективности центрального процессора. Что касается памяти, я предполагаю, что разумная реализация (предполагая, что «необоснованная реализация» «String» «Sun» будет иметь один и тот же базовый массив (от 'all'), поэтому на самом деле будет действительно достаточно эффективная память, что было бы важно для долгосрочная производительность. Если вы только хотите сохранить один из элементов, конечно ... 13 окт. 102010-10-13 22:12:16


0

Просто для удовольствия, решение с помощью jsr166y вилочных присоединиться к структуре, которая должна в 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(); 

(Отказ от ответственности:.. Не компилируется Spec не завершена и т.д.)

маловероятен в JDK7 немного логического вывода типа и синтаксического сахара, чтобы сделать что withMapping вызов менее многословным:

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

0

Это такая основная вещь, что я бы не использовал внешнюю библиотеку (это вызовет зависимость в вашем проекте, что вам, вероятно, не понадобится).

У нас есть класс статических методов, специально созданных для выполнения подобных заданий. Поскольку код для этого настолько прост, мы позволяем Hotspot делать оптимизацию для нас. Это, кажется, тема в моем коде в последнее время: напишите очень простой (простой) код и дайте Hotspot сделать свою магию. У нас редко возникают проблемы с производительностью вокруг кода, подобного этому - когда появляется новая версия VM, вы получаете все дополнительные преимущества по скорости и т. Д.

Насколько мне нравятся коллекции Jakarta, они не поддерживают Generics и используют 1.4 в качестве ЖК-дисплея , Я опасаюсь Google Collections, потому что они указаны как уровень поддержки Alpha!


82

Использование Google Collections from Guava-Project, вы можете использовать метод transform в 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()); 

List возвращаемого transform является вида в списке основы - преобразование будет применяться при каждом доступе к преобразованному список.

Имейте в виду, что Functions.toStringFunction() будет выдавать NullPointerException при применении к нулевому значению, поэтому используйте его, только если вы уверены, что ваш список не будет содержать нуль.

+1

Будет хорошо, если есть более готовые функции рядом с Function.toStringFunction() 07 сен. 102010-09-07 06:58:21

+1

чистым, но, возможно, не таким быстрым .. 1 дополнительный вызов функции за значение? 09 дек. 102010-12-09 15:35:27

+3

HotSpot может выполнять встроенные вызовы функций, поэтому, если это называется достаточно, это не должно иметь значения. 09 дек. 102010-12-09 20:45:53

+3

Я не делаю этого, потому что это действительно решение. Но поощрение людей к добавлению зависимости от библиотеки для решения такой простой задачи - это не для меня. 28 фев. 142014-02-28 19:09:08

+1

Хорошее решение, если вы уже используете Guava в нашем решении. 28 апр. 152015-04-28 12:46:16

+1

Потенциальная проблема заключается в том, что преобразование применяется лениво (потенциально много раз). Вы можете захотеть вернуть 'new ArrayList <> (Lists.transform (integers, Functions.toStringFunction())) вместо этого, чтобы избежать этого, 06 янв. 162016-01-06 10:13:23

  0

Обратный, если вы наткнулись на этот вопрос, ища String -> Number:' Lists.transform (listOfStrings, Ints.stringConverter()); ' 17 фев. 162016-02-17 22:21:55


2

Lambdaj позволяет сделать это очень простым и понятным способом.Например, предположим, что у вас есть список Integer и вы хотите преобразовать их в соответствующее строковое представление, вы можете написать что-то подобное;

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 применяет функцию преобразования только во время повторения результата.


8

Это однострочное решение без обмана с библиотекой, отличной от JDK.

  0

+1 для чистого хакерства. 10 мар. 132013-03-10 19:30:46


-1

Я просто хотел прослушивать объектно-ориентированное решение проблемы.

Если вы моделируете объекты домена, то решение находится в объектах домена. Домен здесь представляет собой список целых чисел, для которых мы хотим использовать строковые значения.

Самый простой способ - не преобразовать список вообще.

Это, как говорится, для того, чтобы преобразовать без преобразования, изменения в первоначальный список Integer к списку стоимости, где стоимость выглядит примерно так ...

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

Это будет быстрее и занимают меньше чем копирование списка.

Удачи!


52

Решение для Java 8. Дольше, чем у Guava, но, по крайней мере, вам не нужно устанавливать библиотеку.

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

Хотя это немного больше для примера «toString», он становится короче для конверсий, не поддерживаемых библиотекой функций Guava. Пользовательские функции по-прежнему легки, но это значительно больше кода, чем этот поток Java 8 24 окт. 172017-10-24 20:17:53


5

Другое решение с использованием гуавы и Java 8

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

0

Я не видел ни одного решения, которое следует за основной космической сложности. Если список целых чисел имеет большое количество элементов, то это большая проблема.

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

Мы можем использовать итератор для достижения того же.

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