web-dev-qa-db-fra.com

Réduire une ArrayList à une nouvelle taille

Dois-je vraiment le mettre en œuvre moi-même?

private void shrinkListTo(ArrayList<Result> list, int newSize) {
  for (int i = list.size() - 1; i >= newSize; --i)
  list.remove(i);
}
58
ripper234

Créez un sous-liste avec la plage d'éléments que vous souhaitez supprimer, puis appelez clear dans la liste renvoyée.

list.subList(23, 45).clear()

Cette approche est mentionnée comme idiome dans la documentation pour List et ArrayList .


Voici un exemple de code entièrement testé unitaire!

// limit yourHappyList to ten items
int k = yourHappyList.size();
if ( k > 10 )
    yourHappyList.subList(10, k).clear();
    // sic k, not k-1
112
mP.

vous pouvez également utiliser la méthode subList :

public static <T> List<T> shrinkTo(List<T> list, int newSize) {
    return list.subList(0, newSize - 1);
}
7
dfa

utilisez la méthode ArrayList # removeRange () :

void removeRange protégé (int fromIndex, int toIndex)

Supprime de cette liste tous les éléments dont l'index est compris entre fromIndex, inclusif, et toIndex, exclusif. Décale tous les éléments suivants vers la gauche (réduit leur index). Cet appel raccourcit la liste par les éléments (toIndex - fromIndex). (Si toIndex == fromIndex, cette opération n'a aucun effet.)

puis utilisez la méthode ArrayList # trimToSize () :

Limite la capacité de cette instance ArrayList à la taille actuelle de la liste. Une application peut utiliser cette opération pour minimiser le stockage d'une instance ArrayList.

5
dfa

Ma solution:

public static void shrinkTo(List list, int newSize) {
    int size = list.size();
    if (newSize >= size) return;
    for (int i = newSize; i < size; i++) {
        list.remove(list.size() - 1);
    }
}

Utilisez simplement:

shrinkTo(yourList, 6);
3
Sergey Shustikov

Il y a une autre considération. Vous souhaiterez peut-être éviter d'utiliser un ArrayList dans votre signature de méthode, et travailler à la place sur l'interface List, car elle vous lie à l'implémentation ArrayList, apportant des modifications à la ligne difficile si vous trouvez que, par exemple, un LinkedList est plus adapté à vos besoins. Empêcher ce couplage serré a un coût.

Une approche alternative pourrait ressembler à ceci:

private void shrinkListTo(List<Result> list, int newSize) {
  list.retainAll(list.subList(0, newSize);
}

Malheureusement, la méthode List.retainAll() est facultative pour les sous-classes à implémenter, vous devrez donc catch an UnsupportedOperationException, Puis faire autre chose.

private void shrinkListTo(List<Result> list, int newSize) {
  try {
    list.retainAll(list.subList(0, newSize);
  } catch (UnspportedOperationException e) {
     //perhaps log that your using your catch block's version.
     for (int i = list.size() - 1; i >= newSize; --i)
        list.remove(i);
     }
  }
}

Ce n'est pas aussi simple que votre original. Si vous n'êtes pas lié à l'instance de la liste que vous transmettez, vous pouvez tout aussi facilement retourner une nouvelle instance en appelant subList(int start, int end), et vous n'auriez même pas besoin de créer une méthode. Ce serait également une implémentation plus rapide, car (dans Java 6), vous obtiendriez une instance d'un AbstractList.SubList Qui contient votre liste, un décalage et une taille Il ne serait pas nécessaire de répéter.

Si vous êtes intéressé par les arguments pour coder en Interfaces plutôt qu'en classes, voir cet article préféré d'Allen Holub

1
akf