Jak przekonwertować tablicę obiektów na tablicę ciągów w Javie

244

Korzystam z następującego kodu, aby przekonwertować tablicę Object na tablicę 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();

Ale zastanawiam się, czy jest na to inny sposób, na przykład:

String_Array=(String[])Object_Array;

Spowodowałoby to jednak błąd wykonania: Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;

Jaki jest właściwy sposób to zrobić?

Szczery
źródło
3
Najbardziej podoba mi się odpowiedź waxwinga: String [] stringArray = Arrays.copyOf (objectArray, objectArray.length, String []. Class); Jest bardzo zwięzły i działa. Policzyłem, ile czasu zajmuje zarówno jego odpowiedź, jak i moje obecne podejście, są one prawie takie same.
Frank

Odpowiedzi:

381

Inna alternatywa dla System.arraycopy:

String[] stringArray = Arrays.copyOf(objectArray, objectArray.length, String[].class);
jemiołucha
źródło
59
tylko na Javie 1.6 i nowszych
newacct
10
Hmm. Nie mogłem zmusić tego do działania, gdzie działa długi przykład z pierwotnego pytania. Zgłasza wyjątek java.lang.ArrayStoreException. Uzyskuję tablicę obiektów z metody toArray na ogólnej tablicy ArrayList zawierającej mój typ niestandardowy. Czy nie oczekuje się, że zadziała to z lekami generycznymi czy coś takiego?
Ian Varley,
4
@Ian, problem polega na tym, że objectArray zawiera Objects not Strings (patrz komentarz mmyers do mojej odpowiedzi, która ma ten sam problem).
Yishai,
3
Właśnie wypróbowałem to podejście i przynajmniej w moim przypadku dowiedziałem się, że wydajność nie jest tak dobra, jak sama budowa tablicy przez iterację. (Szkoda, ale podobało mi się to jako jedna linijka!)
mdup,
1
@mdup - dość długi jeden liner. owinąć to może metodą.
MasterJoe2
72

W Javie 8:

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

Aby przekonwertować tablicę innych typów:

String[] strings = Arrays.stream(obj).map(Object::toString).
                   toArray(String[]::new);
Vitalii Fedorenko
źródło
2
Jest to dzieło piękna i spełnia wymóg estetycznej konwersji tablicy obiektów innych niż String na tablicę ich odpowiedników toString. Aktualnie akceptowana odpowiedź nie osiąga tego.
b4n4n4p4nd4
To działa, ale jeśli twoja lista zawiera wartości null, otrzymasz NullPointerException. Aby obejść ten problem, zobacz: stackoverflow.com/questions/4581407/…
Tony Falabella
61

System.arraycopy jest prawdopodobnie najbardziej wydajnym sposobem, ale dla estetyki wolałbym:

 Arrays.asList(Object_Array).toArray(new String[Object_Array.length]);
Yishai
źródło
10
Działa to tylko wtedy, gdy wszystkie obiekty są ciągami; jego obecny kod działa, nawet jeśli tak nie jest.
Michael Myers
Słuszna uwaga. Zrozumiałem toString jako po prostu sposób rzutowania na String, a nie zamiar faktycznego zastąpienia obiektów czymś innym. Jeśli to właśnie musisz zrobić, zapętlenie jest jedynym sposobem.
Yishai,
to nie działa w Androidzie 2.3.3 .. daje mi błąd, mówiąc, że metoda copyof nie jest zdefiniowana. Zaimportowałem wszystkie właściwe pliki (ctrl + shift + I) .. ale nadal nie działa.
user590849,
3
@ user590849, moja odpowiedź nie jest używana copyof. Czy odnosisz się do innej odpowiedzi?
Yishai
50

Widzę, że niektóre rozwiązania zostały dostarczone, ale nie ma żadnych przyczyn, więc wyjaśnię to szczegółowo, ponieważ uważam, że równie ważne jest wiedzieć, co robiłeś źle, aby uzyskać „coś”, co działa na podstawie podanych odpowiedzi.

Najpierw zobaczmy, co ma do powiedzenia 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.

To może nie wyglądać na ważne, ale jak zobaczysz, to jest ... Więc co zawiedzie następująca linia? Wszystkie obiekty na liście są ciągiem, ale nie konwertuje ich, dlaczego?

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

Prawdopodobnie wielu z was pomyśli, że ten kod robi to samo, ale tak nie jest.

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

Kiedy w rzeczywistości napisany kod robi coś takiego. Jawadok to mówi! Ustanowi nową tablicę, czym będzie Obiektów !!!

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

Zatem tList.toArray tworzy instancję Obiektów, a nie Ciągów ...

Dlatego naturalnym rozwiązaniem, o którym nie wspomniano w tym wątku, ale to, co zaleca Oracle, jest następujące

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

Mam nadzieję, że to dość jasne.

Capagris
źródło
Niewielka wydajność w zakresie korekty: String tArray [] = tList.toArray (new String [tList.size ()]); W przeciwnym razie należy ponownie zmienić rozmiar tablicy ...
Lonzak,
1
Dobre wytłumaczenie. Jeszcze jedna rzecz, jeśli problemem jest zużycie pamięci lub wydajność, nie powielaj tablicy. Albo rzuć element w String, gdy go potrzebujesz, (String)Object_Array[i]albo Object_Array[i].toString()przydziel tablicę jako tablicę String Object Object_Array[]=new String[100];... pobierz wartości ..., a następnie rzut, String_Array=(String[])Object_Arrayktóry teraz działa.
Solostaran14
1
generuje to ArrayStoreException
iltaf khalid
7

Ramy kolekcji Google oferują ofertę dobrej metody transformacji, dzięki czemu można przekształcić obiekty w ciągi znaków. Jedynym minusem jest to, że musi to być od Iterable do Iterable, ale tak bym to zrobił:

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

Odciąga cię to od używania tablic, ale myślę, że to byłby mój preferowany sposób.

Richard
źródło
1
@Yishai: nie, tablice nie implementują Iterable. iteracja nad nimi jest specjalnie zdefiniowana w JLS
newacct
@newacct, całkiem prawda, miałem na myśli, że tablice można łatwo zawijać w Iterable (Arrays.asList ()). Nie wiem, dlaczego tak się stało.
Yishai,
5

Jeśli chcesz uzyskać ciąg znaków reprezentujący obiekty w tablicy, to tak, nie ma innego sposobu, aby to zrobić.

Jeśli wiesz, że tablica obiektów zawiera tylko ciągi znaków, możesz także zrobić (instread wywołania metody toString ()):

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

Jedynym przypadkiem, w którym można użyć rzutowania na String [] obiektu Object_Array, jest sytuacja, w której tablica, do której się ona odwołuje, byłaby faktycznie zdefiniowana jako String [], np. Działałoby to:

    Object[] o = new String[10];
    String[] s = (String[]) o;
David a.
źródło
5

Ten jest fajny, ale nie działa, jak zauważyli mmyers, ze względu na nawiasy kwadratowe:

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

Ten jest brzydki, ale działa:

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

Jeśli używasz tego kodu, musisz mieć pewność, że ciągi zwracane przez obiekt doString () nie zawierają przecinków.

Ilya Boyandin
źródło
1
Ciekawa sugestia, ale najpierw musisz usunąć [i] na pierwszym i ostatnim elemencie.
Michael Myers
1
wspaniale, dopóki nie wykona zadania :)
AZ_
2
To nie działa, jeśli jakikolwiek ciąg zawiera przecinek (,)
Andreas Berger
2

Jeśli chodzi o twój pomysł, faktycznie zbliżasz się do sukcesu, ale jeśli tak, to powinno być w porządku:

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

BTW, użycie narzędzia Arrays jest całkiem dobre i sprawia, że ​​kod jest elegancki.

ttt
źródło
1
Object arr3[]=list1.toArray();
   String common[]=new String[arr3.length];

   for (int i=0;i<arr3.length;i++) 
   {
   common[i]=(String)arr3[i];
  }
Amit Kumar Sagar
źródło
1

Możesz użyć konwertera typów . Aby przekonwertować tablicę dowolnego typu na tablicę ciągów, możesz zarejestrować własny konwerter:

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

i użyj go

   Object[] objects = new Object[] {1, 23.43, true, "text", 'c'};
   String[] strings = TypeConverter.convert(objects, String[].class);
lstypka
źródło
0

Łatwo zmieniaj bez nagłówka Konwertuj dowolną tablicę obiektów na tablicę ciągów Obiekt drivex [] = {1,2};

    for(int i=0; i<drive.length ; i++)
        {
            Str[i]= drivex[i].toString();
            System.out.println(Str[i]); 
        }
Rahul Chhangani
źródło