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

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

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

Ответ 1

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

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

Ответ 2

Используя Google Collections из 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 при применении к null, поэтому используйте его только в том случае, если вы уверены, что ваш список не будет содержать null.

Ответ 3

Решение для 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());

Ответ 4

То, что вы делаете, прекрасно, но если вы чувствуете потребность в "Java-it-up", вы можете использовать Transformer и собрать метод из 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);

Ответ 5

Вместо использования 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()); 
}

Ответ 6

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

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

Не то, чтобы это было важно, но я бы использовал toString.

Ответ 7

Здесь однострочное решение без обмана с помощью библиотеки, отличной от JDK.

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

Ответ 8

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

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

Ответ 9

Не ядро ​​Java, а не generic-ified, но популярная библиотека коллекций коллективных коллекций Jakarta имеет некоторые полезные абстракции для такого рода задач. В частности, посмотрите методы сбора на

CollectionUtils

Что-то, что нужно учитывать, если вы уже используете коллективные фонды в своем проекте.

Ответ 10

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

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

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

Ответ 11

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

Ответ 12

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

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

Ответ 13

Ответ только для экспертов:

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

Ответ 14

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

Ответ 15

List<String> stringList = integerList.stream().map((Object s)->String.valueOf(s)).collect(Collectors.toList())

Ответ 16

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

Ответ 17

Просто для удовольствия, решение, использующее фреймворк jsr166y fork-join, который должен быть в 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(#(Integer i) String.valueOf(i))

Ответ 18

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

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

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

Ответ 19

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

It will be really good to remove the integer from the List<Integer> and free
the space, once it 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();
    }

Ответ 20

Использование потоков: Если, скажем, результат - это список целых чисел (List<Integer> result), то:

List<String> ids = (List<String>) result.stream().map(intNumber -> Integer.toString(intNumber)).collect(Collectors.toList());

Один из способов решить это. Надеюсь это поможет.

Ответ 21

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

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

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

При этом для преобразования без преобразования измените исходный список Integer на List of Value, где Value выглядит примерно так:

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

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

Удачи!