Geçmişte, bir koleksiyonu güvenli bir şekilde kopyalamayı şöyle söyledim:
public static void doThing(List<String> strs) {
List<String> newStrs = new ArrayList<>(strs);
veya
public static void doThing(NavigableSet<String> strs) {
NavigableSet<String> newStrs = new TreeSet<>(strs);
Ancak bu "kopya" kurucuları, benzer statik oluşturma yöntemleri ve akışları gerçekten güvenli midir ve kurallar nerede belirtilmiştir? Güvenli bir şekilde , Java dili tarafından sunulan temel anlamsal bütünlük garantileri ve makul bir kişi tarafından desteklenen SecurityManagerve kusurların olmadığı varsayılarak kötü amaçlı bir arayan için uygulanan koleksiyonlar vardır.
Ben metod atma mutluyum ConcurrentModificationException, NullPointerException, IllegalArgumentException, ClassCastException, vb hatta belki asılı.
StringDeğişmez tipte bir argüman örneği olarak seçtim . Bu soru için, kendi gotcha'ları olan değişebilir tiplerin koleksiyonları için derin kopyalarla ilgilenmiyorum.
(Açık olmak gerekirse, ben OpenJDK kaynak koduna bakıp için cevap çeşit var ArrayListve TreeSet.)
NavigableSetve diğer Comparabletabanlı koleksiyonlar bazen bir sınıfın compareTo()doğru bir şekilde uygulanıp uygulanmadığını tespit eder ve bir istisna atar. Güvenilmeyen argümanlarla ne demek istediğiniz biraz net değil. Yani bir kötü adam kötü Dizeleri bir koleksiyon yapar ve bunları koleksiyonunuza kopyaladığınızda kötü bir şey olur mu? Hayır, koleksiyon çerçevesi oldukça sağlam, 1.2'den beri var.
HashSet(ve genel olarak tüm diğer karma koleksiyonları) doğruluğu / bütünlüğü dayanıyor hashCodeelemanlarının uygulanması, TreeSetve PriorityQueuebağlı Comparator(ve hatta olamaz özel karşılaştırıcıyı kabul etmeden eşdeğer bir kopya oluştur) (varsa), derlemeden sonra hiçbir zaman doğrulanmayan EnumSetbelirli enumtürün bütünlüğüne güvenir , böylece üretilmeyen javacveya el işi olmayan bir sınıf dosyası onu bozabilir.
new TreeSet<>(strs)nerede strsbir olduğunu NavigableSet. Bu toplu bir kopya değildir, çünkü sonuç TreeSet, semantiği korumak için bile gerekli olan kaynağın karşılaştırıcısını kullanacaktır. Sadece içerilen elemanları işlemede iyi iseniz, toArray()gitmek için yoldur; yineleme sırasını bile koruyacaktır. “Elemanı al, elemanı doğrula, elemanı kullan” konusunda sorun yaşıyorsanız, bir kopya bile yapmanız gerekmez. Sorunlar, tüm öğeleri doğrulamak ve ardından tüm öğeleri kullanmak istediğinizde başlar. O zaman, TreeSetözel karşılaştırıcı w kopyalamaya güvenemezsiniz
checkcastHer öğe için a efektine sahip tek toplu kopyalama işlemi toArraybelirli bir türdedir. Biz her zaman bununla bitiyoruz. Genel koleksiyonlar, gerçek öğe türlerini bile bilmezler, bu nedenle kopya oluşturucuları benzer bir işlev sağlayamaz. Tabii ki, herhangi bir kontrolü doğru kullanımdan önce erteleyebilirsiniz, ancak sonra sorularınızın neyi amaçladığını bilmiyorum. Elemanları kullanmadan hemen önce kontrol etme ve hata verme konusunda iyi olduğunuzda "anlamsal bütünlük" e ihtiyacınız yoktur.