重複したキーを持つマップが必要です。
多くのマップ実装があることを知っているので (Eclipse は約 50 を示しています)、これを可能にするものがあるに違いありません。これを行う独自のマップを作成するのは簡単ですが、既存のソリューションを使用したいと思います。
commons-collections または google-collections の何かでしょうか。
重複したキーを持つマップが必要です。
多くのマップ実装があることを知っているので (Eclipse は約 50 を示しています)、これを可能にするものがあるに違いありません。これを行う独自のマップを作成するのは簡単ですが、既存のソリューションを使用したいと思います。
commons-collections または google-collections の何かでしょうか。
マルチマップを探していますが、実際には commons-collections と Guava の両方にそのための実装がいくつかあります。マルチマップでは、キーごとに値のコレクションを維持することで、複数のキーを使用できます。つまり、単一のオブジェクトをマップに配置できますが、取得するのはコレクションです。
Multimap
Java 5 を使用できる場合は、ジェネリックに対応しているため、Guava を使用することをお勧めします。
Google コレクションの外部ライブラリに依存する必要はありません。次のマップを簡単に実装できます。
Map<String, ArrayList<String>> hashMap = new HashMap<String, ArrayList>();
public static void main(String... arg) {
// Add data with duplicate keys
addValues("A", "a1");
addValues("A", "a2");
addValues("B", "b");
// View data.
Iterator it = hashMap.keySet().iterator();
ArrayList tempList = null;
while (it.hasNext()) {
String key = it.next().toString();
tempList = hashMap.get(key);
if (tempList != null) {
for (String value: tempList) {
System.out.println("Key : "+key+ " , Value : "+value);
}
}
}
}
private void addValues(String key, String value) {
ArrayList tempList = null;
if (hashMap.containsKey(key)) {
tempList = hashMap.get(key);
if(tempList == null)
tempList = new ArrayList();
tempList.add(value);
} else {
tempList = new ArrayList();
tempList.add(value);
}
hashMap.put(key,tempList);
}
コードを微調整してください。
通常の HashMap の値に値の配列を渡すだけで、重複キーをシミュレートできます。使用するデータを決定するのはユーザー次第です。
MultiMapを使用することもできますが、私自身は重複キーのアイデアは好きではありません。
(コメントに書いたように)Key-Valueペアのリストについて反復したい場合は、リストまたは配列の方が適しているはずです。まず、キーと値を組み合わせます。
public class Pair
{
public Class1 key;
public Class2 value;
public Pair(Class1 key, Class2 value)
{
this.key = key;
this.value = value;
}
}
Class1とClass2を、キーと値に使用するタイプに置き換えます。
これで、それらを配列またはリストに入れて、それらを反復処理できます。
Pair[] pairs = new Pair[10];
...
for (Pair pair : pairs)
{
...
}
【2021年6月】
MultiValueMap クラス
私はこの問題のわずかに異なるバリアントを持っていました: 2 つの異なる値を同じキーに関連付ける必要がありました。他の人に役立つ場合に備えてここに投稿するだけで、値として HashMap を導入しました。
/* @param frameTypeHash: Key -> Integer (frameID), Value -> HashMap (innerMap)
@param innerMap: Key -> String (extIP), Value -> String
If the key exists, retrieve the stored HashMap innerMap
and put the constructed key, value pair
*/
if (frameTypeHash.containsKey(frameID)){
//Key exists, add the key/value to innerHashMap
HashMap innerMap = (HashMap)frameTypeHash.get(frameID);
innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);
} else {
HashMap<String, String> innerMap = new HashMap<String, String>();
innerMap.put(extIP, connName+":"+frameType+":"+interfaceName);
// This means the key doesn't exists, adding it for the first time
frameTypeHash.put(frameID, innerMap );
}
}
上記のコードでは、入力ファイルの各行の最初の文字列からキー frameID が読み取られます。frameTypeHash の値は、残りの行を分割することによって作成され、当初は String オブジェクトとして格納されていました。同じframeIDキーに関連付けられているため、frameTypeHashは値として最後の行で上書きされました。値フィールドとして String オブジェクトを別の HashMap オブジェクトに置き換えました。これは、単一のキーから異なる値へのマッピングを維持するのに役立ちました。
class DuplicateMap<K, V>
{
enum MapType
{
Hash,LinkedHash
}
int HashCode = 0;
Map<Key<K>,V> map = null;
DuplicateMap()
{
map = new HashMap<Key<K>,V>();
}
DuplicateMap( MapType maptype )
{
if ( maptype == MapType.Hash ) {
map = new HashMap<Key<K>,V>();
}
else if ( maptype == MapType.LinkedHash ) {
map = new LinkedHashMap<Key<K>,V>();
}
else
map = new HashMap<Key<K>,V>();
}
V put( K key, V value )
{
return map.put( new Key<K>( key , HashCode++ ), value );
}
void putAll( Map<K, V> map1 )
{
Map<Key<K>,V> map2 = new LinkedHashMap<Key<K>,V>();
for ( Entry<K, V> entry : map1.entrySet() ) {
map2.put( new Key<K>( entry.getKey() , HashCode++ ), entry.getValue());
}
map.putAll(map2);
}
Set<Entry<K, V>> entrySet()
{
Set<Entry<K, V>> entry = new LinkedHashSet<Map.Entry<K,V>>();
for ( final Entry<Key<K>, V> entry1 : map.entrySet() ) {
entry.add( new Entry<K, V>(){
private K Key = entry1.getKey().Key();
private V Value = entry1.getValue();
@Override
public K getKey() {
return Key;
}
@Override
public V getValue() {
return Value;
}
@Override
public V setValue(V value) {
return null;
}});
}
return entry;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("{");
boolean FirstIteration = true;
for ( Entry<K, V> entry : entrySet() ) {
builder.append( ( (FirstIteration)? "" : "," ) + ((entry.getKey()==null) ? null :entry.getKey().toString() ) + "=" + ((entry.getValue()==null) ? null :entry.getValue().toString() ) );
FirstIteration = false;
}
builder.append("}");
return builder.toString();
}
class Key<K1>
{
K1 Key;
int HashCode;
public Key(K1 key, int hashCode) {
super();
Key = key;
HashCode = hashCode;
}
public K1 Key() {
return Key;
}
@Override
public String toString() {
return Key.toString() ;
}
@Override
public int hashCode() {
return HashCode;
}
}
キーが重複している場合、キーは複数の値に対応している可能性があります。明らかな解決策は、キーをこれらの値のリストにマップすることです。
たとえば、Pythonの場合:
map = dict()
map["driver"] = list()
map["driver"].append("john")
map["driver"].append("mike")
print map["driver"] # It shows john and mike
print map["driver"][0] # It shows john
print map["driver"][1] # It shows mike
念のために言うと、Apache Commons Collections にはMultiMapもあります。もちろん欠点は、Apache Commons が Generics を使用しないことです。
少しハックすると、HashSet を重複キーで使用できます。警告: これは HashSet の実装に大きく依存します。
class MultiKeyPair {
Object key;
Object value;
public MultiKeyPair(Object key, Object value) {
this.key = key;
this.value = value;
}
@Override
public int hashCode() {
return key.hashCode();
}
}
class MultiKeyList extends MultiKeyPair {
ArrayList<MultiKeyPair> list = new ArrayList<MultiKeyPair>();
public MultiKeyList(Object key) {
super(key, null);
}
@Override
public boolean equals(Object obj) {
list.add((MultiKeyPair) obj);
return false;
}
}
public static void main(String[] args) {
HashSet<MultiKeyPair> set = new HashSet<MultiKeyPair>();
set.add(new MultiKeyPair("A","a1"));
set.add(new MultiKeyPair("A","a2"));
set.add(new MultiKeyPair("B","b1"));
set.add(new MultiKeyPair("A","a3"));
MultiKeyList o = new MultiKeyList("A");
set.contains(o);
for (MultiKeyPair pair : o.list) {
System.out.println(pair.value);
}
}
重複キーを使用してマップを実装しようとしているコンテキストについても説明できますか? より良い解決策があると確信しています。マップは、正当な理由で一意のキーを保持することを目的としています。あなたが本当にやりたかったのなら。クラスをいつでも拡張して、衝突軽減機能を持ち、同じキーで複数のエントリを保持できるようにする単純なカスタム マップ クラスを作成できます。
注: 衝突するキーが「常に」一意のセットに変換されるように、衝突緩和機能を実装する必要があります。オブジェクトのハッシュコードなどでキーを追加するような単純なものはありますか?
私はこれを使用しました:
java.util.List<java.util.Map.Entry<String,Integer>> pairList= new java.util.ArrayList<>();