Java 8 neden değişmez koleksiyonlar içermiyor?


130

Java ekibi, Java 8'deki işlevsel programlamanın önündeki engelleri kaldırarak bir sürü harika çalışma yaptı. Özellikle, java.util Collections'taki değişiklikler, çok hızlı akış işlemlerine dönüştürülmesi için büyük bir zincirleme işi yapıyor. Koleksiyonlara birinci sınıf işlevler ve fonksiyonel yöntemler ekleyerek ne kadar iyi yaptıklarını göz önünde bulundurarak, neden değişmez koleksiyonlar ve hatta değişmez koleksiyon arayüzleri sağlayamıyorlar?

Var olan herhangi bir kodu değiştirmeden, Java ekibi herhangi bir zamanda değiştirilebilir olanlarla aynı olan değişken arayüzleri ekleyebilir, "set" yöntemlerini eksi ekleyebilir ve mevcut arayüzlerin bunlardan genişlemesini sağlayabilir:

                  ImmutableIterable
     ____________/       |
    /                    |
Iterable        ImmutableCollection
   |    _______/    /          \   \___________
   |   /           /            \              \
 Collection  ImmutableList  ImmutableSet  ImmutableMap  ...
    \  \  \_________|______________|__________   |
     \  \___________|____________  |          \  |
      \___________  |            \ |           \ |
                  List            Set           Map ...

Tabii, List.add () ve Map.put () gibi işlemler, işlemin başarılı veya başarısız olduğunu belirtmek için şu anda verilen anahtar için bir boolean veya önceki değer döndürüyor. Değiştirilemez koleksiyonların fabrikalar gibi yöntemleri ele alması ve mevcut imzayla uyumlu olmayan eklenen öğeyi içeren yeni bir toplama yapması gerekir. Ancak bu, ImmutableList.append () veya .addAt () ve ImmutableMap.putEntry () gibi farklı bir yöntem adı kullanarak çözülebilir. Sonuçta ortaya çıkan ayrıntılılık, değişmeyen koleksiyonlarla çalışmanın yararlarından daha ağır basacak ve tip sistemi yanlış yöntemi arama hatalarını önleyecektir. Zamanla, eski yöntemler kullanımdan kaldırılabilir.

Değişmez koleksiyonların kazancı:

  • Basitlik - temel verinin değişmediği durumlarda kod hakkında muhakeme daha basittir.
  • Belgeleme - Bir yöntem değişmez bir koleksiyon arayüzüne sahipse, bu koleksiyonu değiştirmeyeceğini bilirsiniz. Bir yöntem değişmez bir koleksiyon döndürürse, onu değiştiremeyeceğinizi bilirsiniz.
  • Eşzamanlılık - değişmeyen koleksiyonlar iş parçacıkları arasında güvenle paylaşılabilir.

Değişmezliği kabul eden dilleri tadayan biri olarak, yaygın mutasyona uğramış vahşi batıya dönmek çok zordur. Clojure'un koleksiyonları (dizi soyutlaması) zaten Java 8 koleksiyonlarının sağladığı her şeye, artı değişkenliğe (akışlar yerine senkronize bağlı listeler nedeniyle ek bellek ve zaman kullanıyor olsa da) zaten sahip. Scala, tam bir işlem setiyle hem değişken hem de değişmeyen koleksiyonlara sahiptir ve bu işlemler istekli olsa da, .iterator'ı tembel bir görünüm verir (ve bunları tembel olarak değerlendirmenin başka yolları da vardır). Java'nın, değişmeyen koleksiyonlar olmadan nasıl rekabet etmeye devam edebileceğini anlamıyorum.

Birisi beni bu konuda tarih veya tartışmalara yönlendirebilir mi? Kesinlikle bir yerlerde halka açık.


9
Bununla ilgili - Ayende son zamanlarda C # 'daki koleksiyonlar ve değişmez koleksiyonlar ile ilgili kıyaslamalarda blog yazdı. ayende.com/blog/tags/performance - tl; dr - değişmezlik yavaştır .
15'te Oded

20
senin hiyerarşinle sana bir ImmutableList verebilirim ve sonra bir çok şeyi kırabilecek bir şey beklemiyorsan, sende sadece constkoleksiyonların olduğu gibi, onu değiştirebilirsin
cırcır

18
@Oded Immutability yavaş, ancak kilitleniyor. Öyleyse bir tarihi korumaktır. Sadelik / Düzeltme birçok durumda hıza değer. Küçük koleksiyonlarda, hız sorun değil. Ayende'nin analizi, tarihe, kilitlemeye veya basitliğe ihtiyaç duymadığınızı ve geniş bir veri kümesiyle çalıştığınızı varsayıyor. Bazen bu doğru, ama her zaman daha iyi bir şey değil. Değişimler var.
GlenPeterson

5
@GlenPeterson savunma kopyalarının ne Collections.unmodifiable*()için olduğunu ve bunun için var. ama bunları olmadıklarında değişmez olarak kabul etmeyin
cırcır ucube

13
Eh? Eğer fonksiyonunuz ImmutableListbu şemaya girerse , insanlar değişkene geçebilir Listmi? Hayır, bu LSP'nin çok kötü bir ihlalidir.
Telastyn

Yanıtlar:


113

Çünkü değişmez koleksiyonlar kesinlikle kullanılabilir olmalarını gerektirir. Aksi halde, her bir işlem başka bir listeyi bir yere yığar. Haskell gibi tamamen değişmeyen diller, agresif optimizasyonlar ve paylaşımlar olmadan şaşırtıcı miktarda çöp üretir. Sadece <50 element ile kullanılabilen koleksiyona sahip olmak standart kütüphaneye koymaya değmez.

Dahası, değişmez koleksiyonlar genellikle değişebilir meslektaşlarından temelde farklı uygulamalara sahiptir. Örneğin düşünün ArrayList, verimli bir değişken ArrayListhiç bir dizi olmaz! Büyük bir dallanma faktörüne sahip dengeli bir ağaç ile uygulanmalıdır, Clojure 32 IIRC kullanır. Değişken koleksiyonları yalnızca işlevsel bir güncelleme ekleyerek "değiştirilemez" yapmak, bir bellek sızıntısı kadar olduğu gibi bir performans hatasıdır.

Ayrıca, paylaşım Java'da geçerli değildir. Java, paylaşımı "sadece bir optimizasyon" yapmak için değişkenlik ve referans eşitliği için çok sayıda sınırsız kanca sağlar. Listedeki bir öğeyi değiştirebilseniz ve sahip olduğunuz listenin diğer 20 sürümünde bir öğeyi değiştirdiğinizi fark ederseniz, muhtemelen biraz üzülecektir.

Bu aynı zamanda, verimli değişmezlik, paylaşım, akış füzyonu için çok önemli optimizasyon sınıflarını da dışlar, mutasyona uğrarsanız, değişkenlik bozar. (Bu FP evangelistleri için iyi bir slogan olur)


21
Örneğim değişmez arayüzlerden bahsetti . Java , gerekli değiş tokuşları yapacak olan arayüzlerin hem değişken hem de değişmez uygulamalarının tam bir paketini sağlayabilir . Uygun şekilde değiştirilebilir veya değişmez seçmek programcının görevidir. Programcılar, bir Listeyi ve Şimdi ayarla'yı ne zaman kullanacaklarını bilmek zorundadır. Genelde bir performans sorununu yaşayıncaya kadar değiştirilebilir versiyona ihtiyacınız yoktur ve bu durumda sadece üretici olarak gerekli olabilir. Her durumda, değişmez ara yüze sahip olmak kendi başına bir kazanç olacaktır.
GlenPeterson

4
Cevabınızı tekrar okudum ve bence Java'nın temel bir değişkenlik varsayımına sahip olduğunu (örn. Java fasulyesi) ve koleksiyonların buzdağının sadece görünen kısmı olduğunu ve bu ipucunun oyulmasının temel sorunu çözmeyeceğini söylüyorsunuz. Geçerli bir nokta. Bu cevabı kabul edebilir ve Scala'nın benimsenmesini hızlandırabilirim! :-)
GlenPeterson

8
Değişmez koleksiyonların ortak parçaları paylaşabilme yeteneğinin kullanılmasını gerektirdiğinden emin değilim. Java'daki en yaygın değişmeyen tür, değişime izin veren bir karakter koleksiyonudur, paylaşmaya izin vermek için kullanılır, ancak artık kullanılamaz. Yararlı kılan en önemli şey, verileri hızlı bir Stringşekilde StringBuffera'dan a'ya kopyalamak, üzerinde değişiklik yapmak ve verileri yeni bir değişkene kopyalamaktır String. Setler ve listelerle böyle bir desen kullanmak, biraz değiştirilmiş örneklerin üretimini kolaylaştırmak için tasarlanmış değişmez tipler kullanmak kadar iyi olabilir, ancak yine de daha iyi olabilir ...
supercat

3
Paylaşım kullanarak Java'da değişmez bir koleksiyon yapmak tamamen mümkündür. Koleksiyonda saklanan ürünler referanslardır ve referansları mutasyona uğratılabilir - peki ne? Bu tür bir davranış zaten HashMap ve TreeSet gibi mevcut koleksiyonları kırar, ancak bunlar Java'da uygulanır. Birden fazla koleksiyon aynı nesneye referanslar içeriyorsa, nesnenin değiştirilmesinin tüm koleksiyonlardan göründüğünde görünür bir değişikliğe neden olması beklenir.
Solomonoff'un Sırrı

4
jozefg, JVM'de yapısal paylaşımla verimli değişmez koleksiyonlar uygulamak tamamen mümkündür. Scala ve Clojure onları standart kütüphanelerinin bir parçası olarak kullanıyor, her iki uygulama da Phil Bagwell'in HAMT'sini (Hash Array Mapped Trie) temel alıyor. BALANCED ağaçları ile değişmez veri yapıları uygulama Clojure hakkındaki ifadeniz tamamen yanlıştır.
sesm

77

Değişken bir koleksiyon değişmez bir koleksiyonun alt türü değildir. Bunun yerine, değişken ve değişken koleksiyonlar, okunabilir koleksiyonların kardeşleridir. Ne yazık ki, "okunabilir", "salt okunur" ve "değişmez" kavramları, üç farklı anlama gelmelerine rağmen birlikte bulanık görünüyor.

  • Okunabilir bir koleksiyon baz sınıfı veya arayüz tipi, bir kişinin öğeleri okuyabileceğini vaat eder ve koleksiyonun değiştirilmesi için herhangi bir doğrudan yol sağlamaz, ancak referansı alan kodun, modifikasyona izin verecek şekilde döküm yapıp işleyemeyeceğini garanti etmez.

  • Salt okunur bir koleksiyon arabirimi, yeni üyeler içermez, ancak yalnızca bir başvuruyu, koleksiyonu mutasyona uğratmak veya bir şeye referans almak gibi bir biçimde manipüle etmenin bir yolu olmadığını vaat eden bir sınıf tarafından gerçekleştirilmelidir. bu yapabilirdi. Bununla birlikte, koleksiyonun iç kısımlara referans olan başka bir şey tarafından değiştirilmeyeceğine söz vermez. Salt okunur bir koleksiyon arabiriminin, değişken sınıflar tarafından uygulanmasını önleyemeyebileceğini, ancak mutasyona izin veren herhangi bir uygulamanın veya bir uygulamadan türetilen bir sınıfın, bir uygulamanın "meşru olmayan" bir uygulaması veya türevi olarak değerlendirileceğini belirtebilir. .

  • Değişmez bir koleksiyon, herhangi bir referans mevcut olduğu sürece daima aynı verileri tutacak bir koleksiyondur. Belirli bir talebe cevap olarak her zaman aynı verileri döndürmeyen değişmez bir arayüzün herhangi bir uygulaması bozulur.

Kuvvetle ilişkili değişken ve değişmez toplama uygulamak veya aynı "okunabilir" türünden türetmek ve okunabilir tip hem türlerini içerir bazen faydalıdır AsImmutable, AsMutableve AsNewMutableyöntemleri. Böyle bir tasarım, bir koleksiyondaki verileri çağırmak için devam etmek isteyen kodlara izin verebilir AsImmutable; Bu yöntem, koleksiyonun değişebilir olması durumunda savunma kopyası oluşturur, ancak zaten değiştirilemezse kopyayı atlar.


1
Mükemmel cevap. Sahte koleksiyonlar iş parçacığı güvenliğine ve zaman geçtikçe onlar hakkında nasıl sebep olacağınıza ilişkin oldukça güçlü bir garanti verebilir. Okunabilir / Salt Okunur koleksiyonu yok. Aslında, liskov alt bölümleme ilkesini onurlandırmak için Salt Okunur ve İnanılmaz, türetilmiş bir sınıfın tür tarafından verilen garantiyi imha edememesini sağlamak için kesin yöntem ve özel üyelerle soyut temel tür olmalıdır. Ya da bir koleksiyonu saran (Salt Okunur) ya da her zaman savunma kopyasını alan (somut) tamamen somut bir tür olmalıdırlar. Guava ImmutableList'in yaptığı budur.
Laurent Bourgault-Roy

1
@ LaurentBourgault-Roy: Hem mühürlü hem de kalıtsal değişmez türlerin avantajları vardır. Bir kişi meşru olmayan bir sınıfın değişmezlerini kırmasına izin vermek istemiyorsa, mühürlü türler buna karşı koruma sunarken, kalıtsal sınıflar hiçbiri önermez. Öte yandan, sakladığı veriler hakkında bir şeyler bilen ve bu konuda hiçbir şey bilmeyen bir türden çok daha kompakt bir şekilde depolamak için veri saklamak mümkün olabilir. Örneğin, intyöntemlerini getLength()ve yöntemlerini içeren bir dizi içine alan bir ReadableIndexedIntSequence türünü düşünün getItemAt(int).
supercat,

1
@ LaurentBourgault-Roy: Verildiği takdirde ReadableIndexedIntSequence, bir tanesi tüm öğeleri bir diziye kopyalayarak dizi destekli değişmez türün bir örneğini üretebilir, ancak belirli bir uygulamanın uzunluk ve ((long)index*index)>>24her öğe için sadece 16777216 döndürdüğünü varsayalım . Bu meşru, değişmez bir tamsayı dizisi olur, ancak onu bir diziye kopyalamak çok büyük bir zaman ve hafıza kaybı olur.
supercat

1
Tamamen katılıyorum. Benim çözümüm size doğruluk verir (bir noktaya kadar), ancak büyük veri setiyle performans elde etmek için baştan beri değişkenlik için kalıcı bir yapıya ve tasarıma sahip olmalısınız. Küçük toplamalar için zaman zaman değişmeyen bir kopya alarak kurtulabilirsiniz. Scala'nın çeşitli programlar hakkında bir analiz yaptığını ve instançlı listelerin% 90'ı gibi bir şeyin 10 ya da daha az öğe olduğunu hatırladım.
Laurent Bourgault-Roy

1
@ LaurentBourgault-Roy: Temel soru, insanlara kırık uygulamalar veya türetilmiş sınıflar üretmemeye güvenip güvenmediğidir. Varsa ve eğer arayüzler / temel sınıflar asMutable / asImmutable metotlar sağlıyorsa, performansı birçok büyüklük asImmutablesırasına göre iyileştirmek mümkün olabilir [örneğin , yukarıda belirtilen bir sekansın bir örneğini çağırmanın maliyetini inşa etme maliyetine karşı karşılaştırın. değişmez bir dizi destekli kopya]. Bu tür amaçlar için tanımlanmış arayüzlere sahip olmanın geçici yaklaşımları kullanmaya çalışmaktan muhtemelen daha iyi olacağını tahmin ediyorum; IMHO, en büyük sebep ...
supercat,

15

Java Collections Framework, java.util.Collections sınıfında altı statik yöntemle bir koleksiyonun salt okunur bir sürümünü oluşturma yeteneği sağlar :

Orijinal soruya yapılan yorumlarda birisinin belirttiği gibi, iade edilen koleksiyonlar değiştirilemez olarak kabul edilemez, çünkü koleksiyonlar değiştirilemese bile (koleksiyon eklenemez veya böyle bir koleksiyondan üye alınamaz), koleksiyon tarafından referans alınan gerçek nesneler Nesne türü izin veriyorsa değiştirilebilir.

Bununla birlikte, bu sorun, kodun tek bir nesneyi mi, yoksa değiştirilemez bir nesne koleksiyonu mu döndürdüğünden bağımsız olarak kalır. Tür nesnelerinin mutasyona uğramasına izin veriyorsa, o zaman tipin tasarımında bu karar verildi ve JCF'de yapılan bir değişikliğin bunu nasıl değiştirebileceğini görmüyorum. Değişmezlik önemliyse, bir koleksiyonun üyeleri değişmez türden olmalıdır.


4
Sargısız koleksiyonların tasarımı, sargılar sarılmakta olan şeyin zaten değişken olup olmadığına dair bir gösterge içeriyorsa ve immutableListgeçenlerin bir kopyasının etrafına salt okunur bir sarıcıyı döndürecek fabrika yöntemleri olsaydı, büyük ölçüde geliştirilecekti . liste geçti-listeye sürece zaten değişmez oldu . Bunun gibi kullanıcı tanımlı türler oluşturmak kolay olurdu, ancak bir sorun için: joesCollections.immutableListyönteminin döndürdüğü nesneyi kopyalaması gerekmediğini fark etmesine imkân yoktu fredsCollections.immutableList.
supercat,

8

Bu çok iyi bir soru. Java'da yazılan ve dünyanın her yerindeki milyonlarca bilgisayarda çalışan tüm kodların, her gün, günün her saatinde, toplam saat döngülerinin yaklaşık yarısının hiçbir şey yapmadan boşa harcanması gerektiği fikrinden zevk alıyorum. işlevler tarafından döndürülüyor. (Ve bu koleksiyonları yarattıktan sonra milisaniyeden fazla toplayanlar.)

Java programcılarının bir yüzdesi unmodifiableCollection(), Collectionssınıf metotları ailesinin varlığının farkındadır , ancak aralarında bile çoğu kişi bununla uğraşmıyor.

Ve onları suçlayamam: okuma yazma gibi davranan, ancak UnsupportedOperationExceptiononun 'yazma' yöntemlerinden herhangi birini çağırmakla hata yaparsanız bir atma yapacak bir arayüz olması çok kötü bir şeydir!

Şimdi, böyle bir arayüz Collectioneksik olur add(), remove()ve clear()yöntemler bir "ImmutableCollection" arayüzü olmaz; bir "Değiştirilemez Koleksiyon" arayüzü olurdu. Aslına bakılırsa, asla bir "Değiştirilebilir Toplama" arayüzü olamaz, çünkü değişmezlik bir uygulamanın özelliğidir, bir arayüzün özelliği değildir. Biliyorum, bu çok net değil; açıklamama izin ver.

Birinin size böyle bir salt okunur koleksiyon arabirimi verdiğini varsayalım; başka bir konuya geçmek güvenli midir? Bunun gerçekten değişmez bir koleksiyonu temsil ettiğinden emin olduğunu bilseydin cevabı "evet" olurdu; ne yazık ki, bir arayüz olduğu için, nasıl uygulandığını bilmiyorsunuz, bu nedenle cevabın hayır olması gerekiyor : bildiğiniz için, aslında değişebilen bir koleksiyonun değiştirilemez (sizin için) bir görüşü olabilir, (ne elde Collections.unmodifiableCollection()edeceğiniz gibi ), bu nedenle başka bir konu değiştirilirken ondan okumaya çalışmak yozlaşmış verilerin okunmasına neden olur.

Yani, temelde tanımladığınız şey "Değiştirilemez" değil, "Değiştirilemez" toplama arayüzleridir. "Değiştirilemez" in basitçe, böyle bir arayüze referansı olanın, altta yatan koleksiyonun değiştirilmesinin engellendiği anlamına geldiğini ve arayüzün zorunlu olarak değiştirilemez olmasından dolayı, arayüzün herhangi bir modifikasyon yönteminden yoksun olmasından dolayı önlenmesi gerektiğini anlamak önemlidir. Altta yatan koleksiyon çok iyi değişebilir olabilir; hakkında hiçbir bilginiz ve kontrolünüz yok.

Değişmez koleksiyonlara sahip olmak için ara yüz değil sınıf olmalılar !

Bu değişmez koleksiyon sınıflarının kesin olması gerekir, böylece böyle bir koleksiyona referans verildiğinde, kendiniz veya referansı olan ne olursa olsun, değişmeyen bir koleksiyon olarak davranacağından emin olduğunuzdan emin olabilirsiniz. onunla yap.

Bu nedenle, java'da (veya herhangi bir diğer zorunlu zorunlu dilde) eksiksiz bir koleksiyona sahip olmak için aşağıdakilere ihtiyacımız olacaktır:

  1. Değiştirilemez koleksiyon arayüzleri kümesi .

  2. Değiştirilemez olanları genişleten bir dizi değişken toplama arayüzü .

  3. Değişken arayüzleri uygulayan ve ayrıca değiştirilemez arayüzleri genişleten bir dizi değişken toplama sınıfı .

  4. Değiştirilemez arayüzleri uygulayan ancak değişmezliği garanti altına almak için çoğunlukla sınıf olarak dolaşan bir dizi değişmez koleksiyon sınıfı .

Yukarıdakilerin hepsini eğlenmek için uyguladım ve bunları projelerde kullanıyorum ve onlar bir cazibe gibi çalışıyorlar.

Java çalışma zamanının bir parçası olmamalarının nedeni, bunun bunun çok fazla / çok karmaşık / anlaşılmasının çok zor olduğu düşünülmesinden kaynaklanıyordu.

Şahsen, yukarıda açıkladığım şeyin bile yeterli olmadığını düşünüyorum; İhtiyaç duyulan bir şey daha, yapısal değişmezlik için bir dizi değişken arayüzler ve sınıflardır . ("Yapısal olarak tanımlanamaz" öneki çok uzun olduğu için basit olarak "Sert" olarak adlandırılabilir.)


Güzel nokta. İki detay: 1. Değiştirilemez koleksiyonlar, özellikle (örnek olarak bir Liste kullanarak) belirli yöntem imzaları gerektirir: List<T> add(T t)- tüm "mutator" yöntemleri, değişikliği yansıtan yeni bir koleksiyon döndürmelidir. 2. Daha iyi veya daha kötüsü için Arayüzler, imzanın yanı sıra sıklıkla bir sözleşmeyi de temsil eder . Seri hale getirilebilir böyle bir arayüz. Benzer şekilde, Karşılaştırılabilir doğru şekilde uygulamayı gerektirir compareTo()düzgün çalışabilmesi ve ideal ile uyumlu olacak şekilde yöntemini equals()ve hashCode().
GlenPeterson

Ah, aklımda kopya kopya mutasyonları bile yoktu. Yukarıda yazdıklarım, gerçekten hiç metodu olmayan , sade, basit, değişmez koleksiyonları ifade eder add(). Ancak, eğer mutator yöntemler değişmez sınıflara eklenecekse, değişmez sınıflara da geri dönmeleri gerekeceğini varsayalım . Yani, orada gizlenen bir sorun varsa, onu göremiyorum.
Mike Nakis,

Uygulamanız kamuya açık mı? Bunu aylar önce sormalıydım. Neyse, benimki: github.com/GlenKPeterson/UncleJim
GlenPeterson 10:15

4
Suppose someone hands you such a read-only collection interface; is it safe to pass it to another thread?Birinin size değiştirilebilir bir koleksiyon arayüzünün bir örneğini geçtiğini varsayalım. Üzerine herhangi bir yöntem çağırmak güvenli midir? Uygulamanın sonsuza dek sürmeyeceğini, bir istisna atmadığını veya arayüzün sözleşmesini tamamen göz ardı ettiğini bilmiyorsunuz. Neden özellikle değişmez koleksiyonlar için çifte standart var?
Doval,

1
IMHO değişken arayüzlere karşı nedeniniz yanlış. Değişmez arayüzlerin değişken bir uygulamasını yazabilirsiniz ve sonra bozulur. Elbette. Ancak bu, sözleşmeyi ihlal ettiğinizde sizin suçunuz. Sadece bunu yapmayı bırak. SortedSetUyumsuz bir uygulama ile seti alt sınıflara ayırmaktan farklı değildir . Ya da tutarsız bir şey geçirerek Comparable. İsterseniz neredeyse her şey kırılabilir. Sanırım, @Doval'ın "çifte standart" ile kastettiği buydu.
maaartinus

2

Değiştirilemeyen koleksiyonlar birbirleriyle kıyaslandığında derinden özyinelemeli olabilir ve nesne eşitliği secureHash'la ise makul derecede etkin olamaz. Buna merkle ormanı denir. Bir toplama haritası için veya bunların içinde, sıralanmış bir harita için (kendi kendini dengeleyen ikili) AVL ağacı gibi olabilir.

Bu koleksiyonlardaki tüm java nesnelerinin benzersiz bir kimliği ya da karmaşasına bir bit çarpması olmadığı sürece, koleksiyonun kendisini benzersiz bir şekilde adlandıracak hiçbir şeyi yoktur.

Örnek: 4x1.6 ghz dizüstü bilgisayarımda, 500 K HashMap op ya da 3M op uzunluğunda bir hash ile karşılaştırıldığında, 1 hash döngüsüne uyan en küçük saniyenin saniyesinde 200K sha256s çalıştırabilirim. 200K / log (collectionSize) saniyede yeni koleksiyonlar, veri bütünlüğü ve adsız küresel ölçeklenebilirliğin önemli olduğu bazı şeyler için yeterince hızlı.


-3

Verim. Koleksiyonlar doğası gereği çok büyük olabilir. Tek bir eleman yerleştirmek yerine 1000 elemanın 1001 elemanla yeni bir yapıya kopyalanması sadece korkunç bir durum.

Eşzamanlılık. Çalışan birkaç iş parçacığınız varsa, iş parçacığı başladığında 12 saat önce geçen sürümü değil koleksiyonun geçerli sürümünü almak isteyebilirsiniz.

Depolama. Çok dişli bir ortamda değişmez nesnelerle, yaşam döngüsünün farklı noktalarında "aynı" nesnenin düzinelerce kopyasını alabilirsiniz. Bir Takvim veya Tarih nesnesi için farketmez, ancak 10.000 widget koleksiyonu olduğunda sizi öldürür.


12
Değiştirilemez koleksiyonlar, yalnızca Java'daki gibi yaygın değişkenlik nedeniyle paylaşamıyorsanız, kopyalamayı gerektirir. Eşzamanlılık, değişmez koleksiyonlarla genellikle daha kolaydır, çünkü kilitlenmeleri gerekmez; ve görünürlük için daima değişmez bir koleksiyon için değişken bir referansa sahip olabilirsiniz (OCaml'de ortaktır). Paylaşma ile güncellemeler aslında ücretsiz olabilir. Mantıksal bir yapıya göre logaritmik olarak daha fazla tahsisat yapabilirsiniz, ancak güncelleme sırasında, süresi dolmuş alt nesneler derhal serbest bırakılabilir veya yeniden kullanılabilir, bu nedenle zorunlu olarak daha fazla hafızanız olmaz.
Jon Purdy

4
Çift problemleri. Clojure ve Scala'daki koleksiyonlar değişmezdir ancak hafif kopyaları destekler. 1001 elemanının eklenmesi, 33 elemandan daha az kopyalamanın yanı sıra birkaç yeni işaretçi yapmak anlamına gelir. Değişken bir koleksiyonu iş parçacıkları arasında paylaşırsanız, değiştirdiğinizde her türlü eşitleme sorunuyla karşılaşırsınız. "Remove ()" gibi işlemler kabus gibi. Aynı zamanda, değişmez koleksiyonlar değiştirilebilir şekilde oluşturulabilir, daha sonra bir kez dişler arasında paylaşılması güvenli, değişmez bir versiyona kopyalanabilir.
GlenPeterson

4
Eşzamanlılığı değişmezliğe karşı bir argüman olarak kullanmak olağandışıdır. Aynı zamanda kopyalar.
Tom Hawtin - alay hattı

4
Buradaki aşağı oylar hakkında biraz sinirliydi. OP neden değiştirilemez koleksiyonlar uygulamadıklarını sordu ve ben soruya düşünülmüş bir cevap verdim. Muhtemelen moda bilinci arasında kabul edilebilir tek cevap "bir hata yaptıkları için" dir. Aslında bununla ilgili mükemmel bir tecrübe sahibiyim, aksi takdirde mükemmel BigDecimal sınıfını kullanarak büyük kod parçalarını yeniden kırmak zorunda kalıyorum, çünkü bu, sadece bir çift artı kullanmanın 512 katının değişmezliği nedeniyle onlukları düzeltmek için etrafa bulaşan karışıklıktan kaynaklanıyor.
James Anderson

3
@JamesAnderson: Cevabınızla ilgili problemlerim: "Performans" - gerçek hayattan etkilenmeyen koleksiyonların her zaman bir tür paylaşım şekli uyguladığını ve tam olarak tanımladığınız konuyu önlemek için tekrar kullandıklarını söyleyebilirsiniz. "Eşzamanlılık" - bağımsız değişken "Değişkenlik istiyorsanız, değiştirilemez bir nesne çalışmaz" ifadesine kadar kısalır. Demek istediğim, "aynı şeyin en son versiyonu" kavramı varsa, o zaman bir şeyin ya da kendisinin ya da o şeyin sahibi olan bir şeyin mutasyona uğraması gerekir. Ve "Depolama" da, değişkenliğin bazen istenmediğini söylüyor gibi görünüyorsunuz.
jhominal,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.