Jak mogę przekonwertować ArrayList <Object> na ArrayList <String>?

95
ArrayList<Object> list = new ArrayList<Object>();
list.add(1);
list.add("Java");
list.add(3.14);
System.out.println(list.toString());

Próbowałem:

ArrayList<String> list2 = (String)list; 

Ale dało mi to błąd kompilacji.

rtf
źródło
5
Dlaczego chcesz to zrobić? Mam na myśli to, że to nie jest bezpieczne. Spójrz na przykład.
Athspk
6
Umieszczasz elementy niebędące łańcuchami na liście. Czego oczekujesz, co się stanie, jeśli zmusisz je do strun?
Ben Zotto,
5
Zakładam, że miałeś na myśli: ArrayList <String> list2 = (ArrayList <String>) list;
Costi Ciudatu,

Odpowiedzi:

132

Ponieważ w rzeczywistości nie jest to lista ciągów, najłatwiejszym sposobem jest zapętlenie jej i samodzielne przekonwertowanie każdej pozycji na nową listę ciągów:

List<String> strings = list.stream()
   .map(object -> Objects.toString(object, null))
   .collect(Collectors.toList());

Lub jeśli nie korzystasz jeszcze z Javy 8:

List<String> strings = new ArrayList<>(list.size());
for (Object object : list) {
    strings.add(Objects.toString(object, null));
}

Lub jeśli nie korzystasz jeszcze z Javy 7:

List<String> strings = new ArrayList<String>(list.size());
for (Object object : list) {
    strings.add(object != null ? object.toString() : null);
}

Zwróć uwagę, że powinieneś deklarować w interfejsie ( java.util.Listw tym przypadku), a nie implementacji.

BalusC
źródło
6
Podoba mi się, jak wartości null są zachowywane w tej implementacji.
4
Jeśli używasz String.valueOf(object), nie będzie musiał wykonać object != null ? object.toString() : nullrzeczą
user219882
2
@Tomas: doda ciąg z wartością "null"zamiast literału null. Zależy to ponadto od wymagań biznesowych, czy jest to pożądane, czy nie. Dla mnie nie byłby to w ogóle do zaakceptowania, ponieważ wprowadza potencjalnie poważny błąd.
BalusC
1
@Tomas: "null"wcale nie jest null. nullMa szczególne znaczenie w Javie. Nie ma sensu być do tego zmuszany if (item.equals("null"))podczas późniejszego sprawdzania tego.
BalusC
1
@Tomas: w ten sposób pokonujesz tylko silną naturę pisania w Javie. Ale jak powiedziałem, to zależy od wymagań biznesowych, czy jest to pożądane. Dla mnie to po prostu niedopuszczalne. Rób, co chcesz, a czas nauczy :)
BalusC
18

Nie jest to bezpieczne!
Wyobraź sobie, że masz:

ArrayList<Object> list = new ArrayList<Object>();
list.add(new Employee("Jonh"));
list.add(new Car("BMW","M3"));
list.add(new Chocolate("Twix"));

Nie miałoby sensu przekształcanie listy tych obiektów na żaden typ.

athspk
źródło
1
Chyba że mają Object#toString()zastąpioną metodę. Jednak cała konwersja typu z X na String do innych celów niż ludzka prezentacja rzeczywiście nie ma większego sensu.
BalusC,
13

Jeśli chcesz to zrobić w brudny sposób, spróbuj tego.

@SuppressWarnings("unchecked")
public ArrayList<String> convert(ArrayList<Object> a) {
   return (ArrayList) a;
}

Zaleta: oszczędzasz czas, nie wykonując iteracji po wszystkich obiektach.

Wada: może spowodować dziurę w stopie.

Per Lindberg
źródło
13

Używając Java 8 możesz:

List<Object> list = ...;
List<String> strList = list.stream()
                           .map( Object::toString )
                           .collect( Collectors.toList() );
Scadge
źródło
12

Korzystanie z guawy :

List<String> stringList=Lists.transform(list,new Function<Object,String>(){
    @Override
    public String apply(Object arg0) {
        if(arg0!=null)
            return arg0.toString();
        else
            return "null";
    }
});
Emil
źródło
10

Możesz użyć symbolu wieloznacznego, aby to zrobić w następujący sposób

ArrayList<String> strList = (ArrayList<String>)(ArrayList<?>)(list);
hellrocker
źródło
8

Oto kolejna alternatywa przy użyciu guawy

List<Object> lst ...    
List<String> ls = Lists.transform(lst, Functions.toStringFunction());
husayt
źródło
5

Twój kod ArrayList<String> list2 = (String)list;nie kompiluje się, ponieważ list2nie jest typu String. Ale to nie jedyny problem.

fastcodejava
źródło
0

Korzystanie z lambda Java 8:

ArrayList<Object> obj = new ArrayList<>();
obj.add(1);
obj.add("Java");
obj.add(3.14);

ArrayList<String> list = new ArrayList<>();
obj.forEach((xx) -> list.add(String.valueOf(xx)));
Ankush soni
źródło
0

Z Java Generics Pobiera listę X i zwraca listę T, która rozszerza lub implementuje X, Sweet!

    // the cast is is actually checked via the method API
@SuppressWarnings("unchecked")
public static <T extends X, X> ArrayList<T> convertToClazz(ArrayList<X> from, Class<X> inClazz, Class<T> outClazz) {
    ArrayList<T> to = new ArrayList<T>();
    for (X data : from) {
        to.add((T) data);
    }
    return to;
}
Tylko ja
źródło
0

Proste rozwiązanie:

List<Object> lst  =listOfTypeObject;   
ArrayList<String> aryLst = new ArrayList<String>();
    for (int i = 0; i < lst.size(); i++) {
        aryLst.add(lst.get(i).toString());
    }

Uwaga: to działa, gdy lista zawiera wszystkie elementy typu danych String.

S Krishna
źródło