HashMap ve int anahtar


104

Anahtar olarak tamsayı ve değer olarak nesneler olacak bir HashMap oluşturmaya çalışıyorum.

Sözdizimim:

HashMap<int, myObject> myMap = new HashMap<int, myObject>();

Ancak, döndürülen hata - "int" belirtecinde sözdizimi hatası, Bu belirteçten sonra beklenen boyutlar - neden bir boyut eklemem gerektiğini anlamıyorum (yani: int'i bir diziye yapmak) çünkü yalnızca bir rakam kaydetmem gerekiyor anahtar olarak.

Ne yapabilirdim?

Şimdiden teşekkürler! :)


14
HashMapilkelleri değil, sadece nesneleri ele alır.
Menno

SO sorusuyla ilgili , ancak intanahtar değil değer olduğu için.
cyroxx

5
IntegerBunun yerine kullanın .
Hot Licks

İnt'i Tamsayı olarak otomatik kutuya almak mı yoksa veriyi sadece bir String olarak saklamak daha mı iyi?
Marcin Erbel

Yanıtlar:


25

HashMap anahtar için dahili olarak nesneyi kullandığından ilkel kullanamazsınız. Dolayısıyla, yalnızca Object'ten miras alınan bir nesneyi (bu herhangi bir nesnedir) kullanabilirsiniz.

Bu, HashMap'teki put () işlevidir ve gördüğünüz gibi K için Object kullanır:

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

"K = e.key" ifadesi bunu netleştirmelidir.

Tamsayı ve otomatik kutulama gibi bir sarmalayıcı kullanmanızı öneririm.


137

IntegerBunun yerine kullanın .

HashMap<Integer, MyObject> myMap = new HashMap<Integer, MyObject>();

Java, intilkel değerlerinizi otomatik olarak Integernesnelere otomatik olarak kutuya alır .

Oracle Java belgelerindeki otomatik kutulama hakkında daha fazla bilgi edinin .


10
Ayrıca bir sınıfa isim vermemelimyObject
Adam Gent

@AdamGent Doğru. Tüm sınıf isimleri büyük harflerle başlamalıdır, önerilen kodu düzelttim.
gaborsch

3
Bildiğini biliyorum :) Sadece OP'nin bildiğinden / öğrendiğinden emin olmak istiyorum. Tek bildiğim tür parametresine bir değişken adı koymuş olabilir.
Adam Gent

1
Sadece hızlı bir küçük not, kullanmak daha iyidir ArrayMapveya SimpleArrayMapbellek performansını arttırır (kaydetmek için Android'de fazla bilgi )
Nuh Huppert

42

Android cihazlar için Java kodlayan ve burada sona eren herkes için: SparseArraydaha iyi performans için kullanın ;

private final SparseArray<myObject> myMap = new SparseArray<myObject>();

bununla Tamsayı yerine int kullanabilirsiniz;

int newPos = 3;

myMap.put(newPos, newObject);
myMap.get(newPos);

7
SparseArray'in hashmap'ten daha yavaş olduğunu, ancak bellek açısından daha verimli olduğunu unutmayın. Bu nedenle, büyük veri kümelerinde kullanmayın.
TpoM6oH

SparseArray yavaşken daha iyi performans için nasıl kullanılır? Android
Snake

@Snake SparseArrayBir grup bellek kutulama ve kutudan çıkarma girişlerini bir ile yaptığınız gibi ayırırsanız, vm'nin HashMapçöp toplama için yürütmeyi daha erken duraklatması gerekecektir. Bir şeyi sık sık ve hızlı bir şekilde yapmaya çalışıyorsanız bu önemlidir.
Jon

1
Sokulma bu karmaşıklığı unutmayın SparseArrayolan O (n) ( HashMapyer alır O (1) ). Eleman sayısının fazla olması önemlidir. Böyle bir dizinin başlangıcına yerleştirme çok daha yavaştır.
Vladimir Petrakovich

1
@ M.kazemAkhgary Tam olarak değil. yerleştirme için başlangıçta put()alır O(n)(değil n log n) çünkü konumu bulur ve ardından takip eden tüm öğeleri kaydırır. delete()kendisi gerçekten alır O(log n), ancak silme işleminden sonra öğeler arasında bir sonraki ekleme veya yineleme, sürecek bir çöp toplama gerektirecektir O(n).
Vladimir Petrakovich


4

HashMap'in anahtar olarak ilkel olmasına izin vermemesinin ana nedeni, HashMap'in anahtarları karşılaştırmak için equals () yöntemini kullanması ve bir yöntemin yalnızca ilkel olmayan bir nesnede çağrılabileceği şekilde tasarlanmış olmasıdır.

Böylece int, Tamsayı olarak otomatik olarak kutulandığında, Hashmap Integer nesnesinde equals () yöntemini çağırabilir .

Bu yüzden int yerine Tamsayı kullanmalısınız. Yani hashmap, int'i anahtar olarak koyarken bir hata atıyor (Atılan hatanın anlamını bilmiyorum)

Ve eğer bunu bir anahtar olarak ilkel yaparak Harita performansını daha hızlı hale getirebileceğinizi düşünüyorsanız, anahtar olarak int tipi olan bir Harita uygulamasını içeren FastUtil adlı bir kütüphane var .

Bu nedenle Hashmap'ten çok daha hızlı


1
Hayır, ilkel türleri izin vermeyerek temel nedeni olan tip silme etkin bir döner Java, Map<Integer, String>içine Map<Object, Object>derleme sırasında. BTW, ==eşitlik kontrolü için operatörü kullanan , hala ilkel türlere izin vermeyen IdentityHashMap var .
Yoory N.

3

HashMap, ilkel veri türlerine bağımsız değişken olarak izin vermez. Yalnızca nesneleri kabul edebilir, bu nedenle

HashMap<int, myObject> myMap = new HashMap<int, myObject>();

çalışmayacak.

Beyanı şu şekilde değiştirmelisiniz

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();

yani aşağıdakileri yaptığınızda bile

myMap.put(2,myObject);

İlkel veri türü, bir Tamsayı nesnesine otomatik olarak kutuya alınır.

8 (int) === boxing ===> 8 (Integer)

Otomatik kutulama hakkında daha fazla bilgiyi burada http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html okuyabilirsiniz.



1

int'i Object olarak kullanın, ilkel tip olarak değil

HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();

Yazılı HashMap <Integer, MyObject> myMap = new HashMap <Integer, MyObject> (); ama gösteriliyor sorunumu> ve <ile iyi bir cevap görüntülemek için
franki3xe

Yazmanın acı verici olduğunu biliyorum ama seni hemen kurtarmaya çalışıyordum -1. Başkalarının cezalandırmadan önce yorum yapmasını beğenmiyorum (seni -1 yapmadım).
Adam Gent

0

Lütfen kullan HashMap<Integer, myObject> myMap = new HashMap<Integer, myObject>();


0

Anahtar olarak sadece bir rakamı saklamam gerektiğinden, neden bir boyut eklemem gerektiğini anlamıyorum (yani: int'i bir diziye dönüştürmek).

Bir dizi aynı zamanda bir Nesnedir, dolayısıyla HashMap<int[], MyObject>int dizilerini anahtar olarak kullanan geçerli bir yapıdır.

Derleyici ne istediğinizi veya neye ihtiyacınız olduğunu bilmez, sadece neredeyse doğru olan bir dil yapısı görür ve tam olarak doğru olması için eksik olanı uyarır.


1
Buna dikkat edin, bir dizinin karma değeri içeriği ile ilgili değildir, bu nedenle aynı içeriğe sahip iki dizi farklı bir değere karma oluşturarak onu çok zayıf bir anahtar haline getirebilir.
john16384

0

İlkel türler yerine sarmalayıcıların Java'daki otomatik kutulamanın ayak izini azaltmak istediğiniz için bu tür bir haritayla ilgilenen birine Eclipse koleksiyonlarını kullanmanızı tavsiye ederim . Trove artık desteklenmiyor ve oldukça güvenilmez bir kütüphane olduğuna inanıyorum (yine de oldukça popüler olmasına rağmen) ve Eclipse koleksiyonlarıyla karşılaştırılamaz .

import org.eclipse.collections.impl.map.mutable.primitive.IntObjectHashMap;

public class Check {
    public static void main(String[] args) {
        IntObjectHashMap map = new IntObjectHashMap();

        map.put(5,"It works");
        map.put(6,"without");
        map.put(7,"boxing!");

        System.out.println(map.get(5));
        System.out.println(map.get(6));
        System.out.println(map.get(7));
    }
}

IntObjectHashMap üzerindeki bu örnekte .

İnt-> nesne eşlemesine ihtiyaç duyduğunuzda , aynı zamanda YourObjectType[]dizinin kullanımını veya List<YourObjectType>indekse göre erişim değerlerini de göz önünde bulundurun , çünkü map, doğası gereği, int tipi indeks olan bir ilişkilendirilebilir dizi.

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.