Harita uygulayan ve ekleme talimatını tutan Java Sınıfı?


463

Java'da anahtar / değer ilişkisi olan, ancak karma kullanmadan bir sınıf arıyorum. Şu anda yaptığım şey:

  1. Bir değerler ekleyin Hashtable.
  2. İçin bir yineleyici alın Hashtable.entrySet().
  3. Tüm değerler arasında yineleme yapın ve:
    1. Map.EntryYineleyici için bir al .
    2. Değere bağlı olarak bir nesne Module(özel sınıf) oluşturun.
    3. Sınıfı bir JPanel'e ekleyin.
  4. Paneli göster.

Bu sorun, ben değerleri geri almak sipariş üzerinde kontrol sahibi olmaması, bu yüzden (sipariş sabit kodlama olmadan) verilen bir sırayla değerleri görüntüleyemezsiniz.

Bunun için bir ArrayListveya kullanırsınız Vector, ancak daha sonra kodda Modulebir ArrayListveya ile yapamam verilen belirli bir Anahtar için nesne kapmak gerekir Vector.

Herkes bunu yapacak ücretsiz / açık kaynaklı bir Java sınıfı veya Hashtablene zaman eklendiklerine göre değerleri almanın bir yolunu biliyor mu?

Teşekkürler!


1
Entryset / map.entry kullanmanıza gerek yoktur. numaralandırma olarak hashtable.keys komutunu veya hashtable.keyset.iterator komutunu kullanarak anahtarlar ve değerler üzerinde yineleme yapabilirsiniz.
John Gardner

5
Başlığı değiştirme özgürlüğünü aldım, çünkü karma kullanmamak aslında sorun değil, ekleme talimatını korumak.
Joachim Sauer

Yanıtlar:


734

A LinkedHashMapveya a öneririm TreeMap. A LinkedHashMapanahtarları yerleştirildikleri sırada tutarken, a öğelerin TreeMapa Comparatorveya doğal düzeniyle sıralanır Comparable.

Öğeleri sıralı tutmak zorunda olmadığından, LinkedHashMapçoğu durumda daha hızlı olmalıdır; TreeMapsahip O(log n)performansını containsKey, get, putve remove, Javadocs göre, süre LinkedHashMapise O(1)her biri için.

Belirli bir sıralama düzeninin aksine, yalnızca öngörülebilir bir sıralama düzeni bekleyen API'niz varsa, bu iki sınıfın uyguladığı arabirimleri kullanmayı düşünün NavigableMapveya SortedMap. Bu, API'nize belirli uygulamaları sızdırmamanıza ve daha sonra bu belirli sınıflara veya tamamen farklı bir uygulamaya geçmenize izin vermez.


2
Bu benim için işe yaramaz, çünkü javadoclara göre, bu sadece sıralı değerler verir (değerler () çağrısı yoluyla). Map.Entry örnekleri sipariş almanın bir yolu var mı?
Cory Kendall

1
@CoryKendall: TreeMap çalışmıyor mu? Değerlere göre değil, anahtarlara göre sıralanması gerekiyor.
Michael Myers

1
Benim hatam, Setlerin ayrılmamış olduğunu düşündüm.
Cory Kendall

61
Lütfen dikkat: Bir TreeMap öğesinin sıralaması anahtarların doğal sırasına bağlıdır: "Harita anahtarlarının doğal sırasına göre sıralanır". LinkedHashMap ekleme sırası ile sıralanır. Büyük fark!
Jop van Raaij

3
@AlexR: Bu yalnızca LinkedHashMap bu amaç için sağlanan özel yapıcı kullanılarak oluşturulmuşsa geçerlidir . Varsayılan olarak, yineleme ekleme sırasındadır.
Michael Myers

22

LinkedHashMap, haritanın keySet (), entrySet () veya değerleri () üzerinde yinelediğinizde öğeleri haritaya eklendikleri sırayla döndürür.

Map<String, String> map = new LinkedHashMap<String, String>();

map.put("id", "1");
map.put("name", "rohan");
map.put("age", "26");

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

Bu, öğeleri haritaya yerleştirildikleri sırayla yazdırır:

id = 1
name = rohan 
age = 26 

16

Değişmez bir harita ihtiyaçlarınızı karşılarsa , google tarafından guava adlı bir kütüphane vardır (ayrıca bkz. Guava soruları )

Guava , kullanıcı tarafından belirlenen güvenilir yineleme sırasına sahip bir ImmutableMap sağlar . Bu ImmutableMap , includeKey , get için O (1) performansına sahiptir. Açıkça koymak ve kaldırmak desteklenmez.

ImmutableMap nesneleri () ve copyOf () öğelerinin zarif statik kolaylık yöntemleri veya bir Builder nesnesi kullanılarak oluşturulur.


6

Bir koruyabilir Map(hızlı arama için) ve List(emrini) ama LinkedHashMapen basit olabilir. Ayrıca , belirlediğiniz herhangi bir siparişi içeren bir SortedMapörneği de deneyebilirsiniz TreeMap.


1

Açık kaynak olup olmadığını bilmiyorum, ancak biraz googling yaptıktan sonra Harita uygulamasını ArrayList kullanarak buldum . 1.5 öncesi Java gibi görünüyor, bu yüzden kolay olması gereken jenerikleştirmek isteyebilirsiniz. Bu uygulamanın O (N) erişimine sahip olduğunu unutmayın, ancak JPanel'inize yüzlerce widget eklemezseniz bu bir sorun olmamalıdır.



1

Önceden bilinen şeylerin doğal düzenini korumam gerektiğinde , bir EnumMap kullanıyorum

anahtarlar numaralandırma olur ve istediğiniz sırada ekleyebilirsiniz, ancak yinelediğinizde numaralandırma düzeninde (doğal düzen) yinelenir.

Ayrıca EnumMap kullanırken daha verimli olabilecek hiçbir çarpışma olmamalıdır.

Gerçekten enumMap kullanarak temiz okunabilir kod için yapar. İşte bir örnek


1

Map'deki ekleme siparişini vermek için LinkedHashMap'i kullanabilirsiniz

Java LinkedHashMap sınıfı hakkında önemli noktalar:

  1. Sadece benzersiz elemanlar içerir.
  2. LinkedHashMap, 3. anahtarı temel alan değerler içerir. Bir boş anahtar ve birden fazla boş değer olabilir. 4. HashMap ile aynıdır, bunun yerine ekleme siparişini korur

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 

Ancak, Kullanıcı tanımlı bir nesne veya herhangi bir ilkel veri türü anahtarı kullanarak haritadaki değerleri sıralamak istiyorsanız, TreeMap kullanmalısınız Daha fazla bilgi için bu bağlantıya bakın


0

Kampanya siparişini koruyan LinkedHashMap<K, V>kendi CustomMap'inizi kullanabilir veya uygulayabilirsiniz .

Sen takiben kullanabilirsiniz CustomHashMapaşağıdaki özelliklere sahip:

  • Ekleme sırası dahili olarak LinkedHashMap kullanılarak korunur.
  • nullDizeleri olan veya boş olan tuşlara izin verilmez.
  • Değerli anahtar oluşturulduktan sonra, değerini geçersiz kılmıyoruz.

HashMapvs LinkedHashMapvsCustomHashMap

interface CustomMap<K, V> extends Map<K, V> {
    public boolean insertionRule(K key, V value);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public class CustomHashMap<K, V> implements CustomMap<K, V> {
    private Map<K, V> entryMap;
    // SET: Adds the specified element to this set if it is not already present.
    private Set<K> entrySet;

    public CustomHashMap() {
        super();
        entryMap = new LinkedHashMap<K, V>();
        entrySet = new HashSet();
    }

    @Override
    public boolean insertionRule(K key, V value) {
        // KEY as null and EMPTY String is not allowed.
        if (key == null || (key instanceof String && ((String) key).trim().equals("") ) ) {
            return false;
        }

        // If key already available then, we are not overriding its value.
        if (entrySet.contains(key)) { // Then override its value, but we are not allowing
            return false;
        } else { // Add the entry
            entrySet.add(key);
            entryMap.put(key, value);
            return true;
        }
    }
    public V put(K key, V value) {
        V oldValue = entryMap.get(key);
        insertionRule(key, value);
        return oldValue;
    }
    public void putAll(Map<? extends K, ? extends V> t) {
        for (Iterator i = t.keySet().iterator(); i.hasNext();) {
            K key = (K) i.next();
            insertionRule(key, t.get(key));
        }
    }

    public void clear() {
        entryMap.clear();
        entrySet.clear();
    }
    public boolean containsKey(Object key) {
        return entryMap.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return entryMap.containsValue(value);
    }
    public Set entrySet() {
        return entryMap.entrySet();
    }
    public boolean equals(Object o) {
        return entryMap.equals(o);
    }
    public V get(Object key) {
        return entryMap.get(key);
    }
    public int hashCode() {
        return entryMap.hashCode();
    }
    public boolean isEmpty() {
        return entryMap.isEmpty();
    }
    public Set keySet() {
        return entrySet;
    }
    public V remove(Object key) {
        entrySet.remove(key);
        return entryMap.remove(key);
    }
    public int size() {
        return entryMap.size();
    }
    public Collection values() {
        return entryMap.values();
    }
}

Kullanımı CustomHashMap:

public static void main(String[] args) {
    System.out.println("== LinkedHashMap ==");
    Map<Object, String> map2 = new LinkedHashMap<Object, String>();
    addData(map2);

    System.out.println("== CustomHashMap ==");
    Map<Object, String> map = new CustomHashMap<Object, String>();
    addData(map);
}
public static void addData(Map<Object, String> map) {
    map.put(null, "1");
    map.put("name", "Yash");
    map.put("1", "1 - Str");
    map.put("1", "2 - Str"); // Overriding value
    map.put("", "1"); // Empty String
    map.put(" ", "1"); // Empty String
    map.put(1, "Int");
    map.put(null, "2"); // Null

    for (Map.Entry<Object, String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " = " + entry.getValue());
    }
}

O / P:

== LinkedHashMap == | == CustomHashMap ==
null = 2            | name = Yash
name = Yash         | 1 = 1 - Str
1 = 2 - Str         | 1 = Int
 = 1                |
  = 1               |
1 = Int             |

KEY'lerin sabit olduğunu biliyorsanız, EnumMap'i kullanabilirsiniz. Özellikler / XML dosyalarından değerler alın

EX:

enum ORACLE {
    IP, URL, USER_NAME, PASSWORD, DB_Name;
}

EnumMap<ORACLE, String> props = new EnumMap<ORACLE, String>(ORACLE.class);
props.put(ORACLE.IP, "127.0.0.1");
props.put(ORACLE.URL, "...");
props.put(ORACLE.USER_NAME, "Scott");
props.put(ORACLE.PASSWORD, "Tiget");
props.put(ORACLE.DB_Name, "MyDB");
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.