2008-08-20 15 views
83

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

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

+1

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

+0

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

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

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

+0

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

2

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

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

+0

+1 для «heartache» ... – Smalltown2k 2010-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 хранит ссылки на объекты. Фактически вы можете опустить параметр и получить «сырой» тип. "Список l = новый список()" по сравнению с "Список l = новый Список ()".конечно, это означает, что «Список l = (Список ) новый список ()« будет фактически скомпилирован и запущен, но, очевидно, очень опасен. – 2011-06-04 20:20:45

3

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

CollectionUtils

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

+4

Никогда не используйте коллекции Apache. Они старые, устаревшие, не безопасные и плохо написанные. – KitsuneYMG 2010-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

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

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

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

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.

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