Collections.emptyMap () ve yeni HashMap () karşılaştırması


143

Kullanabileceğim bazı durumlar Collections.emptyMap()nelerdir? Belgelerim, koleksiyonumun değişmez olmasını istiyorsam bu yöntemi kullanabileceğimi söylüyor.

Neden değişmez boş bir koleksiyon isteyeyim ki? Amaç ne?


12
Soruna +1 + daha önce bu statik yöntemi daha önce hiç görmedim
Tim Bender

ayrıca scala lenslerine google scala lenslerine de göz atabilirsiniz . EmptyMap ve immutableMap, değiştirilemez nesneler oluşturmak için kullanılabilir. emptyMap başlangıç ​​noktasıdır. Bir öğe her eklendiğinde haritanın kendisi eski öğeyi ve yeni öğeleri içeren bir harita ile değiştirilir. Mesele şu ki, nesneye erişim güvenli.
michael_s

1
Objective-C'ler gibi [NSArray array], kullanılabilir olmasa da var olan bir nesneyi döndürür. Böylece normal bir nesne gibi oynayabilir ve hata alamazsınız.
Shane Hsu

Yanıtlar:


144

Gönderen Etkili Java , Ürün # 43 - "Return empty arrays or collections, not null"Boş koleksiyon dönen ortaya koyduğunu ve belki de bu kullanımını gösterir emptyList(), emptySet()ve emptyMap()ayrıca değişmez olmanın katkısı olmadığını Boş koleksiyon almak için Koleksiyonları sınıfı yöntemleri. Gönderen Öğe # 15 "Minimize Mutability" .

Gönderen Koleksiyonları-emptySet-Koleksiyonları-emptyList-Tahsilat

Bu bir tür programlama deyimi. Bu null değişken istemeyen insanlar içindir. Böylece küme başlatılmadan önce boş kümeyi kullanabilirler.

Not: Aşağıdaki kod sadece bir örnektir (kullanım durumunuza göre değiştirin):

private Set myset = Collections.emptySet();

void initSet() {
   myset = new HashSet();
}
void deleteSet() {
   myset = Collections.emptySet();
}

Bu yöntemler birkaç avantaj sunar:

  1. Daha özlüdürler çünkü koleksiyonun genel türünü açıkça yazmanıza gerek yoktur - genellikle yöntem çağrısının bağlamından çıkarılır.

  2. Daha verimli oldukları için yeni nesneler yaratmaya zahmet etmiyorlar; varolan boş ve değişmez bir nesneyi yeniden kullanırlar. Bu etki genellikle çok küçüktür, ancak nadiren (nadiren) önemlidir.


15
Etkili Java başvurusu için +1. Bir nit: Metotlamayı Setve HashSetörneklerinizde tavsiye ederim , çünkü emptySet()yöntemin ve arkadaşların (sabitlerin aksine) bütün noktası Collections.EMPTY_SETjeneriklerle güzel oynamasıdır. Ayrıca, Java 5 iyi bir öğretim yardımı olmadığı için kullanımdan kaldırılmış bir özellik (ham türler) kullanmak.
Daniel Pryden

4
Ben ikna olmadım ... Takip etmenin asıl amacı aşağıdaki operasyonlara atılmaktan Collectionziyade kullanmak değil midir? Değişmez bir koleksiyon kullanmak hayal ettiğim başka bir istisna ile sonuçlanır. Ve atama kesinlikle değişmez bir sabit atamaktan daha az etkili değildir. nullExceptionsnull
fgysin Monica

14
@fgysin: İstemcilerin koleksiyonu değiştirmesi beklenen bir API'nız varsa, evet, değişmez bir koleksiyon döndürmek mantıklı değildir. Ancak, istemcilerin değiştirmemesi ve yalnızca yinelemesi gereken bir koleksiyonu döndürdüğünüz bir API'niz varsa, temel koleksiyona bir görünüm döndürmek, "kötü" bir istemcinin sahip olduğu koleksiyonları yanlışlıkla değiştirmemesini sağlamak için mükemmel bir anlam ifade eder. senin tarafından. Null yerine boş bir koleksiyon döndürmek, istemcinin koleksiyonu kullanmadan önce null bir denetim yapması gerekmediği anlamına gelir ve bu da istemci kodunu daha açık hale getirir.
Jean Hominal

4
public boolean setExists() { return !myset.equals(Collections.emptySet()); }
assylias

5
Örneğinizde, boş kümeyi açıkça kontrol ediyor ve bir sentinel değeri olarak kullanıyorsunuz ve sınıfınız değiştirilebilir. Küçük örneğiniz, tam olarak Collections.emptySet () önlemeye çalıştığı sentinelleri ve değişebilirliği kullanır.
Marc O'Morain

33

Benim kişisel deneyimime göre, bir API'nin parametrelerin toplanmasını gerektirdiği durumlarda, ancak hiçbir şey sunmadığınızda çok kullanışlıdır. Örneğin, şuna benzeyen ve boş referanslara izin vermeyen bir API'nız olabilir:

public ResultSet executeQuery(String query, Map<String, Object> queryParameters);

Herhangi bir parametre almayan bir sorgunuz varsa, etkili bir şekilde sabit olan 'Boş Haritayı' geçebildiğinizde, bir dizi tahsis etmeyi içeren bir HashMap oluşturmak kesinlikle biraz israftır. içinde java.util.Collections.


22

Neden değişmez boş bir koleksiyon isteyeyim ki? Amaç ne?

Burada birlikte bakıldığında garip görünen iki farklı kavram var. İki kavramı ayrı ayrı ele almak daha mantıklıdır.

  • İlk olarak, mümkün olan her yerde değiştirilebilir bir koleksiyon yerine değişmez bir koleksiyon kullanmayı tercih etmelisiniz. Değişmezliğin faydaları başka yerlerde iyi belgelenmiştir .

  • İkinci olarak, null değerini bir sentinel olarak kullanmak yerine boş bir koleksiyon kullanmayı tercih etmelisiniz. Bu burada iyi açıklanmıştır . Bu, daha temiz, anlaşılması daha kolay bir kodun olacağı, hataların daha az saklanacağı anlamına gelir.

Bu nedenle, bir harita gerektiren bir kodunuz olduğunda, bir haritanın bulunmadığını belirtmek için boş bir harita geçmek yerine null değeri kullanmak daha iyidir. Çoğu zaman bir harita kullanırken değişmez bir harita kullanmak daha iyidir. Bu yüzden değişmez boş bir harita yapmak için bir kolaylık fonksiyonu var.


8

Değişmez haritalar, listeler, kümeler veya diğer koleksiyon türlerini kullanmayı tercih edeceğiniz birkaç durum vardır.

İlk ve tartışmasız en önemli kullanım örneği, bir sonuç kümesini (veya listeyi veya haritayı) döndürecek bir sorgunun veya hesaplamanın sonucunu döndürdüğünüzde, değiştirilemez veri yapıları kullanmayı tercih etmelisiniz.

Bu durumda, bunun bir değişmez versiyonunun gerçek değişmezliğini çok daha net bir şekilde yansıttığı için bunların değişmez sürümlerini döndürmeyi tercih ederim - daha sonra verilerle ne yaparsanız yapın, sorgunuzdan aldığınız sonuçların seti değişiklik.

İkinci yaygın kullanım durumu, bir yönteme veya hizmete girdi olarak bir bağımsız değişken sağlamanız gerektiğidir. Giriş koleksiyonunun hizmet veya yöntemle (genellikle gerçekten kötü bir tasarım fikri olan) değiştirilmesini beklemediğiniz sürece , değiştirilebilir bir koleksiyon yerine değişmez bir koleksiyona geçmek birçok durumda makul ve güvenli bir seçim olabilir.

Bunu "değere göre geç" kuralı olarak düşünüyorum .

Daha genel olarak - veri modülü veya hizmet sınırlarını aştığında değişmez bir veri yapısı kullanmak mantıklı bir uygulamadır. Bu, (değiştirilemez) giriş / çıkış ile değişken iç durum arasındaki farkların anlaşılmasını kolaylaştırır.

Bunun çok faydalı bir yan etkisi olarak modüllerinizin / servislerinizin güvenliği ve diş güvenliği artar ve endişelerin daha net ayrılmasını sağlar.

Collections.empty*()Yöntemleri kullanmanın başka bir iyi nedeni , dikkat çekici ayrıntı eksikliği. Java7 öncesi dönemde, genel bir koleksiyonunuz varsa, genel tür ek açıklamalarını her yere serpmek zorundaydınız.

Bu iki bildirimi karşılaştırın:

Map<Foo, Comparable<? extends Bar>> fooBarMap = new HashMap<Foo, Comparable<? extends Bar>>();

karşı:

Map<Foo, Comparable<? extends Bar>> fooBarMap = Collections.emptyMap();

İkincisi, okunabilirliği açıkça iki önemli yolla kazanır:

  1. İlk deklarasyonda, boş bir haritanın tüm somutlaştırılması jenerik tip beyanların gürültüsüne gömülür ve bu da önemsiz bir beyanı olması gerekenden çok daha şifreli hale getirir.
  2. Sağ tarafta jenerik tip ek açıklama eksikliğine ek olarak, ikinci versiyon haritanın boş bir haritaya başlatıldığını açıkça belirtmektedir. Buna ek olarak - bu yöntemin değişmez bir harita döndürdüğünü bilerek, sadece arayarak fooBarMapbaşka bir boş olmayan değer atandığı yeri bulmak artık daha kolay /fooBarMap =/.

5

Birincisi, referans paylaşımı ile kurtulabilirsiniz. Bir new HashMap()vb. Tahsis edilmiş bir nesne ve muhtemelen verileri tutmak için bazı ekstra elemanlar gerektirir, ancak değişmez boş bir koleksiyonun (liste, küme, harita veya benzeri) sadece bir kopyasına ihtiyacınız vardır. Bu, çağırdığınız bir yöntemin bir Haritası kabul etmesi gerektiğinde, ancak düzenlemeye gerek duymadığı zaman bariz bir seçimdir.

Değişmez nesnelerin bazı çok güzel özelliklerini listeleyen (iş parçacığı güvenliği dahil) Josh Bloch'un Etkili Java'sına göz atmanızı öneririm .


3

Bir işlevi döndüren bir işleviniz olduğunda yararlı olabilir immutable collectionve bazı durumlarda döndürülecek veri yoktur, bu nedenle döndürmek yerine geri nulldönebilirsinizemptyMap()

Kodunuzu kolaylaştırır ve önler NullPointerException


3

Çoğu zaman constructoryeni bir tane oluşturmak için a kullanırız empty map. Ama Collections methodsavantajları teklif birkaç bir yaratmak için empty mapkullanıyorstatic method java.util.Collections.emptyMap()

  1. Daha özlüdürler çünkü koleksiyonun genel türünü açıkça yazmanıza gerek yoktur - genellikle yöntem çağrısının bağlamından çıkarılır.

  2. Daha verimli oldukları için yeni nesneler yaratmaya zahmet etmiyorlar; varolan boş ve değişmez bir nesneyi yeniden kullanırlar. Bu etki genellikle çok küçüktür, ancak nadiren (nadiren) önemlidir.


2

Neden değişmez boş bir koleksiyon isteyeyim ki? Amaç ne?

Aynı nedenden dolayı Collections.unmodifiableMap()bir noktada kullanırsınız. Kullanıcı bunu değiştirmeye çalışırsa istisna oluşturan bir Map örneği döndürmek istiyorsunuz. Bu sadece özel bir durum: boş Harita.


1

Neden değişmez boş bir koleksiyon isteyeyim ki? Amaç ne?

Aynı nedenlerden dolayı değişmez nesneler isteyebilirsiniz. Öncelikle, birden fazla iş parçacığının bir nesnenin aynı örneğine erişebileceği ve hepsinin aynı değerleri göreceği bilgisiyle gece güvenli bir şekilde uyuyabileceğiniz için. Bir koleksiyonda hiçbir öğenin bulunmaması, korumak istediğiniz geçerli bir değerdir.

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.