613 Stimmen

Java-Klasse, die Map implementiert und die Einfügereihenfolge beibehält?

Ich bin auf der Suche nach einer Klasse in Java, die Schlüssel-Wert-Zuordnung hat, aber ohne Hashes zu verwenden. Hier ist, was ich derzeit tun:

  1. Hinzufügen von Werten zu einer Hashtable .
  2. Holt einen Iterator für die Hashtable.entrySet() .
  3. Iterieren Sie durch alle Werte und:
    1. Erhalten Sie eine Map.Entry für den Iterator.
    2. Erstellen Sie ein Objekt vom Typ Module (eine benutzerdefinierte Klasse) auf der Grundlage des Wertes.
    3. Fügen Sie die Klasse zu einem JPanel hinzu.
  4. Zeigen Sie das Panel an.

Das Problem dabei ist, dass ich keine Kontrolle über die Reihenfolge habe, in der ich die Werte zurückerhalte, so dass ich die Werte nicht in einer bestimmten Reihenfolge anzeigen kann (ohne die Reihenfolge hart zu kodieren).

Ich würde eine ArrayList o Vector dafür, aber später im Code muss ich die Module Objekt für einen bestimmten Schlüssel, was ich nicht mit einer ArrayList o Vector .

Kennt jemand eine freie/offene Java-Klasse, die dies tut, oder eine Möglichkeit, Werte aus einer Hashtable je nachdem, wann sie hinzugefügt wurden?

Gracias.

4voto

Yash Punkte 8318

Entweder Sie verwenden LinkedHashMap<K, V> oder Sie können Ihre eigene CustomMap die die Einfügereihenfolge beibehält.

Sie können Folgendes verwenden CustomHashMap mit den folgenden Merkmalen:

  • Die Einfügereihenfolge wird beibehalten, indem LinkedHashMap intern verwendet wird.
  • Tasten mit null oder leere Zeichenfolgen sind nicht zulässig.
  • Sobald ein Schlüssel mit einem Wert erstellt wurde, wird sein Wert nicht mehr überschrieben.

HashMap gegen LinkedHashMap gegen CustomHashMap

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();
    }
}

Verwendung von 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             |

Wenn Sie wissen, dass die KEY's festgelegt sind, können Sie EnumMap verwenden. Abrufen der Werte aus Properties/XML-Dateien

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");

1voto

jpalecek Punkte 45829

Ich weiß nicht, ob es Open Source ist, aber nach ein wenig Googeln fand ich diese Implementierung von Map mit ArrayList . Es scheint ein Vor-1.5-Java zu sein, so dass Sie es vielleicht generisch machen wollen, was einfach sein sollte. Beachten Sie, dass diese Implementierung O(N) Zugriff hat, aber das sollte kein Problem sein, wenn Sie nicht Hunderte von Widgets zu Ihrem JPanel hinzufügen, was Sie sowieso nicht tun sollten.

1voto

j2emanue Punkte 56131

Wenn ich die natürliche Ordnung der Dinge, die im Voraus bekannt sind, beibehalten muss, verwende ich eine EnumMap

Die Schlüssel sind Aufzählungen und können in beliebiger Reihenfolge eingefügt werden, aber bei der Iteration wird in der Reihenfolge der Aufzählung (der natürlichen Reihenfolge) vorgegangen.

Auch bei der Verwendung von EnumMap sollte es keine Kollisionen geben, was effizienter sein kann.

Ich finde wirklich, dass die Verwendung von enumMap für sauberen, lesbaren Code sorgt. Hier ist eine Beispiel

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X