次の2つのキーと値を含むMap.Entry
要素を取得したい場合は、それは本当に多くなりますより自然なクラスPair<String, String>
を作成して、1つの要素の2つのキーを結合し、1つのマップのキーとして使用しますネストマップではなく
あなたがこれを行う場合は、あなたの主な構造はMap<Pair<String, String>, String>
なり、Map.entrySet()
メソッドを使用すると、あなたがあなたが後にしているものを約与えイテレータを取得することができ、そこからSet<Map.Entry<String, String>, String>
を与えるだろう。
その他の理由でMap<String, Map<String, String>>
が必要な場合は、これを上記の構造に合理的に単純なコードで変換することもできます。これは、情報を取得する最も賢明な方法です。
編集注:
上記Pair
クラスは、基本的にMap.Entry
と同じであるので、あなたはMap<Map.Entry<String, String>, String>
を構築することにより、キーの新しいクラスを作成しないようにできます。私はそれがコードを少し明確にしないと思うが、それは確かに機能的に同等にされることができる。
サンプルコード以下のコードで
、私は(実際の使用のために、あなたは独立したクラスとして抽出したい場合があります)内部staticとしてPair
クラスを定義し、かかる変換を書かれていますあなたが説明するようにネストされたマップを作成し、私が提案したフォームに変換し、変換されたマップのエントリにイテレータを使用して値を出力します。
もちろん、イテレータは他のものにも使用でき、convert
メソッドとPair
クラスは汎用です。
import java.util.*;
public class TestMap
{
public static void main(String[] args)
{
Map<String, String> innerMap1 = new HashMap<String, String>();
Map<String, String> innerMap2 = new HashMap<String, String>();
Map<String, Map<String, String>> outerMap = new HashMap<String, Map<String, String>>();
innerMap1.put("InnerKey1", "Val1");
innerMap1.put("InnerKey2", "Val2");
innerMap1.put("InnerKey3", "Val3");
innerMap1.put("InnerKey4", "Val4");
innerMap2.put("InnerKey5", "Val5");
innerMap2.put("InnerKey6", "Val6");
innerMap2.put("InnerKey7", "Val7");
innerMap2.put("InnerKey8", "Val8");
outerMap.put("OuterKey1", innerMap1);
outerMap.put("OuterKey2", innerMap2);
Map<Pair<String, String>, String> convertedMap = convert(outerMap);
for (Map.Entry<Pair<String, String>, String> entry: convertedMap.entrySet()) {
System.out.println(String.format("OuterKey: %s, InnerKey: %s, Value: %s",
entry.getKey().getFirst(),
entry.getKey().getSecond(),
entry.getValue()
));
}
}
private static <K1,K2,V> Map<Pair<K1, K2>,V> convert(Map<K1, Map<K2,V>> nestedMap) {
Map<Pair<K1, K2>, V> result = new HashMap<Pair<K1, K2>, V>();
for (Map.Entry<K1, Map<K2, V>> outerEntry: nestedMap.entrySet()) {
final K1 outerKey = outerEntry.getKey();
for (Map.Entry<K2, V> innerEntry: outerEntry.getValue().entrySet()) {
final K2 innerKey = innerEntry.getKey();
final V value = innerEntry.getValue();
result.put(new Pair<K1, K2>(outerKey, innerKey), value);
}
}
return result;
}
public static class Pair<T1, T2> {
private T1 first;
private T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public T1 getFirst() {
return first;
}
public T2 getSecond() {
return second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair pair = (Pair) o;
if (first != null ? !first.equals(pair.first) : pair.first != null) return false;
if (second != null ? !second.equals(pair.second) : pair.second != null) return false;
return true;
}
@Override
public int hashCode() {
int result = first != null ? first.hashCode() : 0;
result = 31 * result + (second != null ? second.hashCode() : 0);
return result;
}
}
}
文脈での取り扱い上の注意:あなたの現在のコードで
、あなたはの大きさのためのあなたの古いネストされた形でマップのフィールドcentralMap
を持つクラス、および整数カウンタを持っています地図。代わりに、すべてのネストされたマップを使用しての、あなたが示唆したフォームのマップには、このフィールドを変更する場合は、この方法を
@Override
public String put(final String row, final String column, final String value) {
/**
* Second map which is contained by centralMap, that contain Strings as Keys
* and Values.
*/
Map<String, String> nestedMap;
if (centralMap.containsKey(row))
nestedMap = centralMap.get(row);
else
nestedMap = new HashMap<String, String>();
if (!nestedMap.containsKey(column))
counter++;
centralMap.put(row, nestedMap);
return nestedMap.put(column, value);
}
ます:
この含まれるクラスは、次のようになりますエントリを追加するための方法を持っています
@Override
public String put(final String row, final String column, final String value) {
Pair<String, String> key = new Pair(row, column);
if (centralMap.contains(key)
counter++;
centralMap.put(key, value);
}
そして、それは常にcentralMap.size()
と同じ値が含まれますよう、あなたは実際には、もはやカウンタを必要としない。少し簡単になります。
更新:
昨日に入れて編集から
が、今、削除、それは今(編集履歴から)私には明らかだあなたは、単一のイテレータを構築したいという正しいのマップのすべてのイテレータに委譲キーと値の両方を含む単純な構造体を返します。
これは確かに可能です。後で時間がある場合は、サンプルコードを追加することがあります。別の応答で指摘されているように、iterator.remove()
方法は不可能または不自然かもしれない。
一方、あなたの要件(同じ他の応答に関するコメントに記載されている)は、グアバのTable
で提供されているものとかなり似ています。それはオープンソースであり、それを見るとあなたにアイデアを与えるかもしれません。あなたはdownload the source for guava hereです。
具体的には、グアバのStandardTable
に、のように見える内部クラスCellIterator
が、そこにある:
private class CellIterator implements Iterator<Cell<R, C, V>> {
final Iterator<Entry<R, Map<C, V>>> rowIterator
= backingMap.entrySet().iterator();
Entry<R, Map<C, V>> rowEntry;
Iterator<Entry<C, V>> columnIterator
= Iterators.emptyModifiableIterator();
@Override public boolean hasNext() {
return rowIterator.hasNext() || columnIterator.hasNext();
}
@Override public Cell<R, C, V> next() {
if (!columnIterator.hasNext()) {
rowEntry = rowIterator.next();
columnIterator = rowEntry.getValue().entrySet().iterator();
}
Entry<C, V> columnEntry = columnIterator.next();
return Tables.immutableCell(
rowEntry.getKey(), columnEntry.getKey(), columnEntry.getValue());
}
@Override public void remove() {
columnIterator.remove();
if (rowEntry.getValue().isEmpty()) {
rowIterator.remove();
}
}
}
それはグアバで他のものに依存してあなただけにこのコードをコピーすることはできませんが、それは基本を示していあなたがしなければならないことのパターン。
すべてのネストされたマップのすべてのエントリを通過するイテレータが必要ですか?それですか? –
はい、どうぞ! – ZelelB