Як перетворити об’єктний масив у рядковий масив у Java


244

Я використовую наступний код для перетворення масиву об'єктів у масив String:

Object Object_Array[]=new Object[100];
// ... get values in the Object_Array

String String_Array[]=new String[Object_Array.length];

for (int i=0;i<String_Array.length;i++) String_Array[i]=Object_Array[i].toString();

Але мені цікаво, чи є інший спосіб зробити це, на кшталт:

String_Array=(String[])Object_Array;

Але це призведе до помилки виконання: Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

Який правильний спосіб це зробити?


3
Найкраще мені подобається відповідь waxwing: String [] stringArray = Arrays.copyOf (objectArray, objectArray.length, String []. Class); Це дуже стисло і працює. Я порахував, скільки часу знадобиться як для його відповіді, так і для мого теперішнього підходу, вони майже однакові.
Френк

Відповіді:


381

Ще одна альтернатива System.arraycopy:

String[] stringArray = Arrays.copyOf(objectArray, objectArray.length, String[].class);

59
лише на Java 1.6 і вище
newacct

10
Грн. Я не міг змусити цього працювати, де працює приклад довгої форми в оригінальному запитанні. Це кидає java.lang.ArrayStoreException. Я отримую об’єктний масив з методу toArray на загальному ArrayList, що містить мій спеціальний тип. Чи не очікується, що це працюватиме з дженериками чи щось?
Ян Варлі

4
@Ian, проблема полягає в тому, що objectArray містить об'єкти, а не рядки (див. Коментар mmyers до моєї відповіді, який страждає від тієї ж проблеми).
Yishai

3
Я просто спробував такий підхід, і, принаймні, в моєму випадку, я виявив, що продуктивність не настільки хороша, як сама побудова масиву за допомогою ітерації. (Дуже шкода, мені це сподобалось як
однолінійний

1
@mdup - досить довгий один вкладиш. можливо, оберніть його методом.
MasterJoe2

72

На Java 8:

String[] strings = Arrays.stream(objects).toArray(String[]::new);

Для перетворення масиву інших типів:

String[] strings = Arrays.stream(obj).map(Object::toString).
                   toArray(String[]::new);

2
Це витвір краси та задовольняє вимогу можливості естетично перетворити масив об'єктів, що не є String, у масив їх еквівалентів toString. Наразі прийнята відповідь цього не досягає.
b4n4n4p4nd4

Це працює, але якщо ваш список містить нулі, ви отримаєте NullPointerException. Щоб обійти цю проблему, дивіться: stackoverflow.com/questions/4581407/…
Тоні Фалабелла

61

System.arraycopy - це, мабуть, найефективніший спосіб, але для естетики я вважаю за краще:

 Arrays.asList(Object_Array).toArray(new String[Object_Array.length]);

10
Це працює лише якщо об'єктами є всі рядки; його поточний код працює, навіть якщо їх немає.
Майкл Майєрс

Гарна думка. Я зрозумів, що ToString є лише способом передавання рядка, а не наміром фактично замінити об'єкти чимось іншим. Якщо це те, що вам потрібно зробити, то петля - це єдиний спосіб.
Ісіхай

це не працює в Android 2.3.3 .. це дає мені помилку, сказавши, що метод copyof не визначений. Я імпортував усі потрібні файли (ctrl + shift + I) .. але це все ще не працює.
користувач590849

3
@ user590849, моя відповідь не використовується copyof. Ви переглядаєте іншу відповідь?
Ісіхай

50

Я бачу, що були запропоновані деякі рішення, але не будь-які причини, тому я поясню це докладно, оскільки я вважаю, що важливо знати, що ви робили неправильно, щоб просто отримати "щось", що працює з наведених відповідей.

Спочатку давайте подивимось, що має сказати Oracle

 * <p>The returned array will be "safe" in that no references to it are
 * maintained by this list.  (In other words, this method must
 * allocate a new array even if this list is backed by an array).
 * The caller is thus free to modify the returned array.

Це може не виглядати важливо, але як ви побачите, що це ... Отже, що робить наступний рядок невдалим? Усі об'єкти у списку є String, але він не перетворює їх, чому?

List<String> tList = new ArrayList<String>();
tList.add("4");
tList.add("5");
String tArray[] = (String[]) tList.toArray();   

Напевно, багато хто з вас подумає, що цей код робить те саме, але це не так.

Object tSObjectArray[] = new String[2];
String tStringArray[] = (String[]) tSObjectArray;

Коли насправді написаний код робить щось подібне. Яводок це каже! Він встановить новий масив, що це буде за Об'єкти !!!

Object tSObjectArray[] = new Object[2];
String tStringArray[] = (String[]) tSObjectArray;   

Отже tList.toArray створює об'єкти, а не рядки ...

Тому природне рішення, яке не згадувалося в цій темі, але саме Oracle рекомендує, наступне

String tArray[] = tList.toArray(new String[0]);

Сподіваюся, це досить зрозуміло.


Незначна ефективність корекції: розумна tArray [] = tList.toArray (нова String [tList.size ()]); Інакше масив потрібно змінити знову ...
Lonzak

1
Гарне пояснення. Ще одна річ, якщо споживання пам'яті або продуктивність є проблемою, не дублюйте масив. Або кинути елемент рядка щоразу , коли вам це потрібно (String)Object_Array[i]або Object_Array[i].toString()або виділити масив як масив рядків Object Object_Array[]=new String[100];... отримати значення ... потім відливала String_Array=(String[])Object_Arrayякий тепер працює.
Солостаран14

1
це кидає ArrayStoreException
iltaf khalid

7

Рамка колекцій google пропонує цитувати хороший метод перетворення, тож ви можете перетворити свої об’єкти в рядки. Єдиним недоліком є ​​те, що він повинен бути від Iterable to Iterable, але це так, як я це зробив би:

Iterable<Object> objects = ....... //Your chosen iterable here
Iterable<String> strings = com.google.common.collect.Iterables.transform(objects, new Function<Object, String>(){
        String apply(Object from){
             return from.toString();
        }
 });

Це позбавить вас від використання масивів, але я думаю, що це було б моїм кращим способом.


1
@Yishai: ні, масиви не реалізують Iterable. ітерація над ними спеціально визначена в JLS
newacct

@newacct, цілком вірно, я мав на увазі, що масиви можна легко загорнути в Iterable (Arrays.asList ()). Я не знаю, чому так вийшло.
Yishai

5

Якщо ви хочете отримати струнне представлення об'єктів у своєму масиві, то так, іншого способу це зробити не існує.

Якщо ви знаєте, що масив Object містить лише рядки, ви також можете робити (замість виклику toString ()):

for (int i=0;i<String_Array.length;i++) String_Array[i]= (String) Object_Array[i];

Єдиний випадок, коли ви могли використовувати кастинг для String [] Object_Array, це, якщо масив, на який він посилається, буде фактично визначений як String [], наприклад, це буде працювати:

    Object[] o = new String[10];
    String[] s = (String[]) o;

5

Цей приємний, але не працює, як помітили mmyers, через квадратні дужки:

Arrays.toString(objectArray).split(",")

Цей некрасивий, але працює:

Arrays.toString(objectArray).replaceFirst("^\\[", "").replaceFirst("\\]$", "").split(",")

Якщо ви використовуєте цей код, ви повинні бути впевнені, що рядки, повернені toString () об'єктів, не містять коми.


1
Цікава пропозиція, але спочатку потрібно буде видалити [і] на першому та останньому елементах.
Майкл Майерс

1
чудовий, поки він не виконає роботу :)
AZ_

2
Це не працює, якщо будь-яка рядок містить кому (,)
Андреас Бергер

2

Що стосується вашої ідеї, то насправді ви наближаєтесь до успіху, але якщо вам це подобається, це буде добре:

for (int i=0;i<String_Array.length;i++) String_Array[i]=(String)Object_Array[i];

До речі, використання утиліти Arrays досить непогано і робить код елегантним.



1

Можна використовувати конвертер типів . Для перетворення масиву будь-яких типів у масив рядків ви можете зареєструвати власний конвертер:

 TypeConverter.registerConverter(Object[].class, String[].class, new Converter<Object[], String[]>() {

        @Override
        public String[] convert(Object[] source) {
            String[] strings = new String[source.length];
            for(int i = 0; i < source.length ; i++) {
                strings[i] = source[i].toString();
            }
            return strings;
        }
    });

і використовувати його

   Object[] objects = new Object[] {1, 23.43, true, "text", 'c'};
   String[] strings = TypeConverter.convert(objects, String[].class);

0

Легко змінювати без головного перетворення Перетворити будь-який об’єктний масив у рядковий масив Object drivex [] = {1,2};

    for(int i=0; i<drive.length ; i++)
        {
            Str[i]= drivex[i].toString();
            System.out.println(Str[i]); 
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.