Вопрос

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

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

Это было полезно?

Решение

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

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

Другие советы

Используя Коллекции Google из Guava-Project, вы могли бы использовать transform метод в Списки класс

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.

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

То, что вы делаете, прекрасно, но если вы чувствуете необходимость в "Java-it-up", вы могли бы использовать Трансформатор и тот способ сбора От Общее Достояние Apache, например:

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

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

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

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

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

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

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

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

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

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

Коллекционирование утилит

Кое-что, что следует учитывать, если вы уже используете коллекции commons в своем проекте.

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

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

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

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

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

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

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

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

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

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

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

Просто для развлечения, решение с использованием фреймворка 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();

(Отказ от ответственности:Не скомпилирован.Спецификация еще не завершена.И т.д.)

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

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

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

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

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

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

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

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

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

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

При этом, чтобы преобразовать без преобразования, измените исходный список целых чисел на список значений, где Значение выглядит примерно так...

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

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

Удачи вам!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top