2015-09-13 18 views
13

içeren sık sık kendimi aşağıdakileri yaparak bulmak: Listede kümesinin "damping" içindekiler gibiHashSet performansını

HashSet<String> set = new HashSet<String>(); 
//Adding elements to the set 
ArrayList<String> list = new ArrayList<String> (set); 

şey. Genelde eklediğim öğeler çoğaltmak istediğim iki kopya içerdiğinden ve bunu kaldırmak için kolay bir yol gibi görünüyor. aklında sadece o amaçla

(kaçınarak çiftleri) Ben de yazabilirsiniz:

ArrayList<String> list = new ArrayList<String>(); 
// Processing here 
if (! list.contains(element)) list.add(element); 
//More processing here 

Ve böylece listeye seti "damping" gerek yok. Ancak, her bir öğeyi eklemeden önce küçük bir kontrol yapıyordum (ki bu da HashSet'in de yaptığı gibi)

İki olasılıktan herhangi biri daha verimli mi?

+0

Sorunun ilk bölümünü yanlış yaptınız. Sette çöplüklerden kurtulmak için sette çöplük yapıyorsunuz, değil mi? – MirMasej

+0

Neden sınmıyorsunuz? Btw, seti niçin bir listeye dönüştürmeyi tercih etmiyor? Setin içinden geçmek büyük olasılıkla büyük diziler için daha hızlı olacaktır. – luk32

+0

Merhaba, yorumlarınız için teşekkür ederiz. Bu senaryoda setimi verilerle dolduruyorum (çiftleri önlemek için) ve sonra bir listeye döküyorum, bu şekilde tek bir liste yok. Listeye ihtiyacım olmasaydı aslında bir tane oluşturmazdım, ancak bazen bir sıralama daha sonra uygular ve çalıştığım kodun bir kısmı listeler gerektirir. – Jorge

cevap

30

seti çok daha iyi performans (liste için O(n^2) vs O(n)) verecek ve aynı kaçınarak kümesinden çok amaçlı çünkü bu normal. Sık sık contains çalıştırmak gerekiyorsa bir HashSetO(1) listesi için O(n) karşılaştırıldığında, bu nedenle bir listesini kullanmak asla edilir için

içerir.

+0

Eğer liste sadece birkaç eleman içeriyorsa? –

+1

Karmaşıklık hesaplama gerçekten sınırlanmış sorunlara geçerli değildir. Amacı, sorun boyutu arttıkça sonsuz büyük olma sırasında hesaplama olur ne kadar yavaş anlamaktır. Ben 'contains' operasyon için karma kümesi üzerinden bir listesini kullanarak bir avantaj orada hiç sanmıyorum söyledi . Tabii, bir dizi genel olarak daha büyük bir bellek yüke sahiptir, ancak birkaç unsurlar varsa sadece neden umurunda ki? Daha verimli seti uygulamaları sınırlı veri setleri (örneğin 'EnumSet') için var, ancak genellikle basit bir karma seti Genellikle biz zaten biz' .contains' çalıştırmak zorunda olduğu için geçici bir liste var tipik performans gereksinimleri – Dici

+0

için yeterli olmalıdır. Soru, bir Set oluşturmak için hangi boyuttan anlam çıkar? 10 öğenin altında, her ikisi de 1-2 mikron ölçeğinde çalışır, ancak bir Set oluşturmak için zaman harcıyoruz. Bir sıralama düzeni varsa Neyse, burada bir 'TreeSet' birileri ilgilenen https://gist.github.com/ibalashov/0138e850e58942569a636dffa75f0bb9 Ben' LinkedHashSet' daha bahsetmek istiyorum –

6

ArrayList, verileri depolamak için bir dizi kullanır. ArrayList.contains, O (n) karmaşıklığından olacaktır. Yani dizide tekrar tekrar arama dizisi O(n^2) karmaşıklığa sahip olacak.

HashSet, öğeleri ilgili kovalara depolamak için karma mekanizma kullanır. HashSet'un çalışması, uzun değerler listesi için daha hızlı olacaktır. Öğeye O(1)'da ulaşacaktır.

3

Bir listeye ihtiyacınız yoksa, bir Set kullanırdım ve bu, sipariş önemli değilse ve kopyaları yok saymak istiyorsanız kullanılacak doğal koleksiyondur.

Her ikisini de yapabilirsiniz, bir çoğaltmadan bir Listeye ihtiyacınız var.

private Set<String> set = new HashSet<>(); 
private List<String> list = new ArrayList<>(); 


public void add(String str) { 
    if (set.add(str)) 
     list.add(str); 
} 

listesi benzersiz değerler yalnızca içerir Bu şekilde, orijinal ekleme talimatı korunmuş ve işlem, O olduğu (1).

+3

sipariş konularda eğer kullanılıp kullanılamayacağını hızlı kriter, ya gereksinimi – Dici

+0

Çok basit ve çok şık! Ben gusta! – Jorge

+0

@Jorge not: ilk kez eklenmişse Set.add (x) tek gerçek döndürür. –

0

Listeye eleman ekleyebilirsiniz. Ardından dedup için - sadece DeDup ile bir dizi gerekiyorsa o benzersiz değerleri sadece sahip olması için

HashSet<String> hs = new HashSet<>(); // new hashset 
hs.addAll(list); // add all list elements to hashset (this is the dedup, since addAll works as a union, thus removing all duplicates) 
list.clear(); // clear the list 
list.addAll(hs); // add all hashset elements to the list 

, ayrıca, farklı bir sette addAll() kullanabilirsiniz.