2016-04-18 14 views
0

HashMapのユーザーインターフェイスを作成しようとしています。ユーザーは、キーの順序を乱すことなく値を変更したり、キーの名前を変更することができます。私は検索し、LinkedHashMapを見つけました。ほとんどの場合、キーの順序が保持されていました。しかし、名前を変更した後にキーを削除して追加すると、キーが最後に追加されます。そこで、LinkedHashMapクラスをオーバーライドし、changeKeyName()関数を追加しました。JAVA - 変更キー名機能を使用したHashMapの実装

今では(私の場合は)機能しますが、改善できるかどうかは不思議でした。私は使用していた機能をオーバーライドするだけです。それを完了させるために他のどの機能をオーバーライドする必要がありますか?

ありがとうございます。

private static class OrderedHashMap<K, V> extends LinkedHashMap<K, V> { 

     ArrayList<K> keys = new ArrayList<K>(); 

     @Override 
     public V put(K key, V value) { 
      if (!keys.contains(key)) 
       keys.add(key); 
      return super.put(key, value); 
     } 

     @Override 
     public V remove(Object key) { 
      keys.remove(key); 
      return super.remove(key); 
     } 

     @Override 
     public Set<K> keySet() { 
      LinkedHashSet<K> keys = new LinkedHashSet<K>(); 
      for (K key : this.keys) { 
       keys.add(key); 
      } 
      return keys; 
     } 

     public void changeKeyName(K oldKeyName, K newKeyName) { 
      int index = keys.indexOf(oldKeyName); 
      keys.add(index, newKeyName); 
      keys.remove(keys.get(index + 1)); 
      V value = super.get(oldKeyName); 
      super.remove(oldKeyName); 
      super.put(newKeyName, value); 
     } 

     @Override 
     public Set<Map.Entry<K, V>> entrySet() { 
      final OrderedHashMap<K, V> copy = this; 
      LinkedHashSet<Map.Entry<K, V>> keys = new LinkedHashSet<Map.Entry<K, V>>(); 
      for (final K key : this.keys) { 
       final V value = super.get(key); 
       keys.add(new Map.Entry<K, V>() { 
        @Override 
        public K getKey() { 
         return key; 
        } 

        @Override 
        public V getValue() { 
         return value; 
        } 

        @Override 
        public V setValue(V value) { 
         return copy.put(getKey(), value); 
        } 
       }); 
      } 
      return keys; 
     } 
    } 

EDIT:私は理由が十分に明確ではなかったと思います。ここ

はコードです。以下のキーを追加したとしましょう。

{"key1":"value1"}, 
{"key2":"value2"}, 
{"key3":"value3"}, 
{"key4":"value4"} 

たとえば、「key2」のキー名を変更したいとします。しかし、これもユーザインタフェースであるため、キーの順序は同じままでなければなりません。
私はいくつかの調査をしましたが、キーを削除してから新しいキー名を同じ値に再設定する以外は何もできないことがわかりました。私たちは「key2a」にそのと変更「KEY2」を行うのであれば:

{"key1":"value1"}, 
{"key3":"value3"}, 
{"key4":"value4"}, 
{"key2a":"value2"} 

そして、何が欲しいがこれです:

{"key1":"value1"}, 
{"key2a":"value2"}, 
{"key3":"value3"}, 
{"key4":"value4"} 

だから私はちょうどArrayListの中のキーを保持したときにentrySet()それらを返さkeySet()メソッドが呼び出されます。

+1

** **キー*は変更しないでください。あなたがそうした場合、あなたの 'Map.Entry'は間違ったハッシュバケットになります! –

+0

@ElliottFrischだから、 'entrySet()'と 'keySet()'関数をオーバーライドするべきではありませんか?私は実際にキーを変更するのではなく、新しい名前を削除して追加するからです。 – ossobuko

+0

* changeKeyName()を呼び出すコードを追加してください。* –

答えて

0

LinkedHashMapのカスタムサブクラスではなく、単にTreeMapクラスを使用しているとお考えですか?キーにComparableインターフェイスを実装すると、注文が維持されます。

0

値が格納されているコレクションのハッシュ関数に影響を与えずにキーを変更できるようにするには、次のようなカスタムクラスを試してください。

private class VariableKeyMap { 

    private LinkedHashSet<K, V> myCollection = new LinkedHashSet<K, V>(); 
    private HashMap<int, K> aliases = new HashMap<int, K>(); 
    int id = 0; 

    public void addEntry(K key, V value) { 
     id += 1; 
     aliases.put(K, id); 
     myCollection.put(id, V); 
    } 

    public V getValue(K key) { 
     return myCollection.get(aliases.get(key)); 
    } 

    ... 
} 

実際に値の格納場所に影響を与えずにキーエイリアスを更新できます。

public void changeKey(K oldKey, K newKey) { 
    int currentId = aliases.get(oldKey); 
    aliases.remove(oldKey); 
    aliases.put(newKey, currentId); 
} 
関連する問題