Dans le passé, j'ai dit que pour copier une collection en toute sécurité, faites quelque chose comme:
public static void doThing(List<String> strs) {
List<String> newStrs = new ArrayList<>(strs);
ou
public static void doThing(NavigableSet<String> strs) {
NavigableSet<String> newStrs = new TreeSet<>(strs);
Mais ces constructeurs de «copie», des méthodes de création statique similaires et des flux, sont-ils vraiment sûrs et où sont les règles spécifiées? Par sûr, j'entends les garanties d' intégrité sémantique de base offertes par le langage Java et les collections appliquées contre un appelant malveillant, en supposant SecurityManagerqu'elles soient sauvegardées par un raisonnable et qu'il n'y a pas de défauts.
Je suis heureux avec le lancement de la méthode ConcurrentModificationException, NullPointerException, IllegalArgumentException, ClassCastException, etc., ou peut - être même accroché.
J'ai choisi Stringcomme exemple d'argument de type immuable. Pour cette question, je ne suis pas intéressé par les copies complètes pour les collections de types mutables qui ont leurs propres pièges.
(Pour être clair, j'ai regardé le code source d'OpenJDK et j'ai une sorte de réponse pour ArrayListet TreeSet.)
NavigableSetet d'autres Comparablecollections basées peuvent parfois détecter si une classe ne s'implémente pas compareTo()correctement et lever une exception. On ne sait pas trop ce que vous entendez par arguments non fiables. Vous voulez dire qu'un malfaiteur crée une collection de mauvaises cordes et lorsque vous les copiez dans votre collection, quelque chose de mauvais se produit? Non, le cadre des collections est assez solide, il existe depuis la 1.2.
HashSet(et toutes les autres collections de hachage en général) repose sur l'exactitude / l'intégrité de la hashCodemise en œuvre des éléments, TreeSetet PriorityQueuedépend de la Comparator(et vous ne pouvez même pas créer une copie équivalente sans accepter le comparateur personnalisé s'il en existe un), EnumSetfait confiance à l'intégrité du enumtype particulier qui n'est jamais vérifié après la compilation, de sorte qu'un fichier de classe, non généré javacou fabriqué à la main, peut le subvertir.
new TreeSet<>(strs)où strsest un NavigableSet. Ce n'est pas une copie en bloc, car le résultat TreeSetutilisera le comparateur de la source, ce qui est même nécessaire pour conserver la sémantique. Si vous êtes prêt à simplement traiter les éléments contenus, toArray()c'est la voie à suivre; il conservera même l'ordre d'itération. Lorsque vous êtes d'accord avec "prendre élément, valider élément, utiliser élément", vous n'avez même pas besoin d'en faire une copie. Les problèmes commencent lorsque vous souhaitez vérifier tous les éléments, puis en utilisant tous les éléments. Ensuite, vous ne pouvez pas faire confiance à une TreeSetcopie avec un comparateur personnalisé
checkcastpour chaque élément, concerne toArrayun type spécifique. Nous y terminons toujours. Les collections génériques ne connaissent même pas leur type d'élément réel, de sorte que leurs constructeurs de copie ne peuvent pas fournir une fonctionnalité similaire. Bien sûr, vous pouvez reporter tout contrôle à une bonne utilisation antérieure, mais je ne sais pas à quoi vos questions visent. Vous n'avez pas besoin d '«intégrité sémantique», lorsque vous êtes prêt à vérifier et à échouer immédiatement avant d'utiliser des éléments.