Преобразование List <Integer> в List <String>

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

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
111
0
201 403
22
Перейти к ответу Данный вопрос помечен как решенный

Ответы 22

Ответ принят как подходящий

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

List<Integer> oldList = ...
/* Specify the size of the list up front to prevent resizing. */
List<String> newList = new ArrayList<>(oldList.size());
for (Integer myInt : oldList) { 
  newList.add(String.valueOf(myInt)); 
}

Когда это просто, это называется красотой.

Elbek 07.09.2012 20:11

Исходный плакат, казалось, указывал на то, что он думал об этом, но считал это решение слишком сложным или утомительным. Но мне сложно представить, что может быть проще. Да, иногда вам нужно написать 3 или 4 строки кода, чтобы выполнить работу.

Jay 07.09.2012 21:44

Но это привязывает вас к ArrayList. Можно ли это сделать, используя ту же реализацию, что и в исходном списке?

alianos- 10.04.2013 14:23

@Andreas oldList.getClass (). NewInstance () будет делать

Lluis Martinez 09.05.2013 20:56

Красиво и чисто.

Adnan 01.10.2020 15:32

@Jonathan: Я могу ошибаться, но я считаю, что String.valueOf () в этом случае вызовет функцию String.valueOf (Object), а не будет вставлен в String.valueOf (int). String.valueOf (Object) просто возвращает «null», если он равен нулю, или вызывает Object.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()); 
}

как указал Том Хотин в «выигравшем» ответе, нельзя использовать Listпоскольку это всего лишь интерфейс.

Stu Thompson 15.09.2008 03:11

Хех, я знал это. Я просто написал код, не пробуя его. Я исправлю это в своем ответе.

ScArcher2 15.09.2008 22:24

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

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

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

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

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

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

компилятор НЕ достаточно умен для этого. Когда запускается javac, он фактически удаляет всю информацию о типах обобщенных типов. Базовая реализация коллекции универсальных шаблонов ВСЕГДА хранит ссылки на объекты. Фактически вы можете опустить параметризацию и получите "сырой" вид. "List l = new List ()" по сравнению с "Listl = новый список() ". Конечно, это означает, что" Listl = (Список) новый List() "на самом деле будет компилироваться и запускаться, но, очевидно, очень опасно."

Dave Dopson 05.06.2011 00:20

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

CollectionUtils

Что следует учитывать, если вы уже используете в своем проекте общие коллекции.

Никогда не используйте коллекции Apache. Они старые, устаревшие, небезопасные и плохо написанные.

KitsuneYMG 07.03.2010 15:51

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

CollectionUtils.collect (collectionOfIntegers, новый org.apache.commons.collections.functors.StringValueTransform‌ er ()); Но StringValueTransformer использует String.valueOf ...

Kannan Ekanath 17.02.2010 17:12

Если над коллекциями apache не была проделана новая работа, они не делают дженериков.

KitsuneYMG 07.03.2010 15:50

Это действительно Java-ing-it down. Это не идиоматическая Java, а больше похоже на функциональное программирование. Может быть, когда мы получим замыкания в Java 8, вы сможете назвать это идиоматической Java.

Christoffer Hammarström 08.01.2012 02:44

Вы определенно хотите использовать для этого Collections4 (а не старые коллекции 3.x) для поддержки дженериков: commons.apache.org/proper/commons-collections/apidocs/org/…

JRA_TLL 06.01.2016 13:17

Определение нового класса просто для того, чтобы быть «более ООП или идиоматическим» ... Я не понимаю, чем это лучше, чем простой цикл for-each. Это требует большего количества кода и отодвигает функциональность (что может быть смягчено анонимными классами, но все же). Этот функциональный стиль становится полезным только тогда, когда есть приличный синтаксис (т.е. лямбда-выражения, начиная с Java 8), как функциональные языки обеспечивали его десятилетиями.

TheOperator 01.02.2016 00:02

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

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

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

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

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

Это работает, но за счет неэффективности. Строки Java - это два байта на символ, поэтому "," добавляет четырехбайтовую фиксированную стоимость на целое число перед подсчетом самого целого числа .... среди прочего.

Robert Christian 14.10.2010 01:59

Я думаю, что регулярное выражение может быть больше проблемой с точки зрения необработанной эффективности цикла процессора. Что касается памяти, я полагаю, что разумная реализация (при условии, что неразумная реализация String "Sun") будет использовать один и тот же массив резервных копий (из all), поэтому на самом деле будет достаточно эффективно использовать память, что было бы важно для долгосрочной производительности. Если, конечно, вы не хотите сохранить только один из элементов ...

Tom Hawtin - tackline 14.10.2010 02:12

Просто для удовольствия, решение, использующее структуру fork-join 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();

(Заявление об ограничении ответственности: не скомпилировано. Спецификация не доработана и т. д.)

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

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

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

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

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

Используя Коллекции 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.

Было бы неплохо, если бы помимо Functions.toStringFunction () было больше готовых функций

ThiamTeck 07.09.2010 10:58

чисто, но, может быть, не так быстро .. 1 дополнительный вызов функции на значение?

h3xStream 09.12.2010 18:35

HotSpot может встраивать вызовы функций, поэтому, если он вызывается достаточно, это не имеет значения.

Ben Lings 09.12.2010 23:45

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

estani 28.02.2014 23:09

Хорошее решение, если вы уже используете Guava в нашем решении.

dudinha-dedalus 28.04.2015 15:46

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

JRA_TLL 06.01.2016 13:13

Обратное, если вы наткнулись на этот вопрос в поисках String -> Number: Lists.transform(listOfStrings, Ints.stringConverter());

LateralFractal 18.02.2016 01:21

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

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

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

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

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

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

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

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

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

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

Удачи!

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

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

lightswitch05 24.10.2017 23:17

Вот и «обратный» путь для будущих читателей. Спасибо трейказ! Коллекцияключи = бла-бла-бла; КоллекцияkeyInts = keys.stream (). map (Integer :: parseInt) .collect (Collectors.toLi‌ st ());

granadaCoder 17.10.2020 13:14

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

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

I didn't see any solution which is following the principal of space complexity. If list of integers has large number of elements then it's big problem.

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

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

@RequiresApi (api = Build.VERSION_CODES.N)

Adnan 01.10.2020 15:32

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

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

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

Чуть более краткое решение с использованием метода forEach из исходного списка:

    List<Integer> oldList = Arrays.asList(1, 2, 3, 4, 5);
    List<String> newList = new ArrayList<>(oldList.size());
    oldList.forEach(e -> newList.add(String.valueOf(e)));

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