Quelle est la meilleure façon d'aplatir un ArrayList<Object>
qui contient à la fois des ArrayList<Object>
ArrayList<String>
et String
dans un ArrayList<String>
plat?
Exemple
Entrée: [item1, item2, item3, [item4a, item4b, item4c]]
Résultat attendu: [item1, item2, item3, item4a, item4b, item4c]
Code pour créer un exemple factice:
| for (Object s : item) { for-each not applicable to expression type required: array or java.lang.Iterable found: java.lang.Object
Solution (non) fonctionnelle
private ArrayList<String> flattenList(ArrayList<Object> objectList) { ArrayList<String> flatLst = new ArrayList<String>(); for (Object item : objectList) { if (item.getClass() == ArrayList.class) { System.out.println(item); for (Object s : item) { flatLst.add(String.valueOf(s)); } } else if (item.getClass() == String.class) { flatLst.add(String.valueOf(item)); } } return flatLst; }
Cela donne l'erreur suivante.
ArrayList<Object> objectList = new ArrayList<Object>(); objectList.add("item1"); objectList.add("item2"); objectList.add("item3"); ArrayList<String> subList = new ArrayList<String>(); subList.add("item4a"); subList.add("item4b"); subList.add("item4c"); objectList.add(subList);
Question : comment résoudre ce problème? Ou peut-être mieux, quelle est la meilleure façon de résoudre ce problème?
4 Réponses :
Vous devez aider le compilateur en castant l'élément comme ceci:
private ArrayList<String> flattenList(ArrayList<Object> objectList) { return objectList.stream() .flatMap(this::extract) .collect(Collectors.toCollection(ArrayList::new)); } private Stream<String> extract(Object item) { if (item.getClass() == ArrayList.class) { return ((List<String>) item).stream(); } else if (item.getClass() == String.class) { return Stream.of((String) item); } return Stream.empty(); }
Ou si vous voulez une solution élégante, vous pouvez utiliser des flux comme ceci:
for (Object s : (List) item) {
Merci! Cependant, j'obtiens la non-static variable this cannot be referenced from a static context
erreur qui non-static variable this cannot be referenced from a static context
Que vouliez-vous dire @Andy? Quelle solution cause ce problème?
Je ne sais pas trop quel était le problème exact ici, lorsque j'essayais de compiler, j'obtenais l'erreur ci-dessus. Merci de votre aide! J'ai récompensé @Abra pour sa concision
Les boucles for-each nécessitent des tableaux ou une instance de Iterable
comme opérande de droite. Le type d' item
est Object
, vous devez donc d'abord le lancer.
if (item.getClass() == ArrayList.class) { ArrayList list = (ArrayList) item; for (Object s : list) { flatLst.add(String.valueOf(s)); } }
Utilisation de l' API de flux
List<String> flat = objectList.stream() .map(obj -> (obj instanceof List) ? (List<Object>) obj : List.of(obj)) .flatMap(list -> list.stream()) .map(obj -> String.valueOf(obj)) .collect(Collectors.toList());
Au-dessus du code imprime ...
[item1, item2, item3, item4a, item4b, item4c]
Comme demandé. List<String>
au lieu de List<Object>
ArrayList<Object> objectList = new ArrayList<Object>(); objectList.add("item1"); objectList.add("item2"); objectList.add("item3"); ArrayList<String> subList = new ArrayList<String>(); subList.add("item4a"); subList.add("item4b"); subList.add("item4c"); objectList.add(subList); List<Object> flat = objectList.stream() .map(obj -> (obj instanceof List) ? (List<Object>) obj : List.of(obj)) .flatMap(list -> list.stream()) .collect(Collectors.toList()); System.out.println(flat);
C'est génial, merci. Comment le faire renvoyer une List<String>
au lieu de List<Object>
?
Voici une autre façon de faire la même chose si vous devez le faire en utilisant loop. Si vous pouvez utiliser java8 que la solution par YCF_L, c'est mieux.
public static ArrayList<String> flattenList(ArrayList<Object> objectList) { ArrayList<String> flatLst = new ArrayList<String>(); for (Object item : objectList) { if (item instanceof List) { System.out.println(item); for (Object s : (List)item) { flatLst.add(String.valueOf(s)); } } else if (item instanceof String ) { flatLst.add(String.valueOf(item)); } } return flatLst; }