Сведения о вопросе

Killer

21:13, 9th August, 2020

Теги

java   string   collections   integer    

Преобразование списка в список

Просмотров: 719   Ответов: 19

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

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



  Сведения об ответе

SEEYOU

23:16, 4th August, 2020

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


  Сведения об ответе

lourence

04:04, 9th August, 2020

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

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


  Сведения об ответе

VERSUION

05:41, 22nd August, 2020

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

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


  Сведения об ответе

FAriza

01:50, 27th August, 2020

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


  Сведения об ответе

FAriza

21:09, 16th August, 2020

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


  Сведения об ответе

piter

03:03, 9th August, 2020

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

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

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


  Сведения об ответе

SSESION

14:03, 20th August, 2020

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

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


  Сведения об ответе

SSESION

06:02, 2nd August, 2020

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

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


  Сведения об ответе

KOMP

20:56, 7th August, 2020

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

CollectionUtils

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


  Сведения об ответе

lesha

03:04, 17th August, 2020

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

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

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


  Сведения об ответе

davran

00:00, 26th August, 2020

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

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


  Сведения об ответе

SILA

06:08, 24th August, 2020

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


  Сведения об ответе

P_S_S

01:14, 27th August, 2020

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

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


  Сведения об ответе

lats

10:29, 6th August, 2020

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

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


  Сведения об ответе

repe

09:10, 27th August, 2020

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


  Сведения об ответе

dump

02:25, 4th August, 2020

Просто для удовольствия, решение с использованием jsr166y fork-join framework, который должен быть в 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))


  Сведения об ответе

PAGE

03:09, 18th August, 2020

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

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

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


  Сведения об ответе

appple

14:15, 13th August, 2020

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

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


  Сведения об ответе

DO__IT

10:49, 15th August, 2020

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

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

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

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

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

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

Удачи Вам!


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться