Javaで複数キーを持つMapを使用してみる

# 1. はじめに
* 簡単にJavaでMapをネストして操作したい

# 2. 開発環境
* Java8
* Eclipse

# 3. Mapメソッドの使用例
## 3.1. V put(K key, V value)
* 指定された値と指定されたキーをこのマップで関連付けます。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);

// 結果確認
System.out.println(map);
```

```java
{JPN={TOKYO=100}}
```

## 3.2. V get(Object key)
* 指定されたキーがマップされている値を返します。このマップにそのキーのマッピングが含まれていない場合はnullを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);

// 親キー指定あり
System.out.println(map.get("JPN"));
// 親＋子キー指定あり
System.out.println(map.get("JPN").get("TOKYO"));
```

```java
{TOKYO=100}
100
```

## 3.3. int size()
* このマップ内のキー値マッピングの数を返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OOSAKA", 200);

// キー指定なし
System.out.println(map.size());
// 親キー指定あり
System.out.println(map.get("JPN").size());
```

```java
1
2
```

## 3.4. boolean containsKey(Object key)
* 指定のキーのマッピングがこのマップに含まれている場合にtrueを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OOSAKA", 200);

// キー指定なし
System.out.println(map.containsKey("JPN"));
// 親キー指定あり
System.out.println(map.get("JPN").containsKey("NAGOYA"));
```

```java
true
false
```

## 3.5. boolean containsValue(Object value)
* マップが1つまたは複数のキーを指定された値にマッピングしている場合にtrueを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OOSAKA", 200);

// 親キー指定あり
System.out.println(map.get("JPN").containsValue(200));
```

```java
true
```

## 3.6. void clear()
* マップからマッピングをすべて削除します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.put("USA", new HashMap<String,Integer>());
map.get("USA").put("NY", 300);

// 親キー指定あり
map.get("JPN").clear();
System.out.println(map);

// キー指定なし
map.clear();
System.out.println(map);
```

```java
{USA={NY=300}, JPN={}}

```

## 3.7. Set<Map.Entry<K,V>> entrySet()
* このマップに含まれるマッピングのSetビューを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.put("USA", new HashMap<String,Integer>());
map.get("USA").put("NY", 300);

// キー指定なし
System.out.println(map.entrySet());

// 親キー指定あり
System.out.println(map.get("JPN").entrySet());
```

```java
[USA={NY=300}, JPN={TOKYO=100}]
[TOKYO=100]
```

## 3.8. Set<K> keySet()
* このマップに含まれるキーのSetビューを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.put("USA", new HashMap<String,Integer>());
map.get("USA").put("NY", 300);

// キー指定なし
System.out.println(map.keySet());

// 親キー指定あり
System.out.println(map.get("JPN").keySet());
```

```java
[USA, JPN]
[TOKYO]
```

## 3.9.Collection<V> values()
* このマップに含まれる値のCollectionビューを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.put("USA", new HashMap<String,Integer>());
map.get("USA").put("NY", 300);

// キー指定なし
System.out.println(map.values());

// 親キー指定あり
System.out.println(map.get("JPN").values());
```

```java
[{NY=300}, {TOKYO=100}]
[100]
```

## 3.10. default boolean remove(Object key)
* 指定された値に指定されたキーが現在マッピングされている場合にのみ、そのキーのエントリを削除します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);

// 子キー指定あり
map.get("JPN").remove("TOKYO");
System.out.println(map);

// 親キー指定あり
map.remove("JPN");
System.out.println(map);
```

```java
{JPN={OSAKA=200}}
{}
```

## 3.11 default boolean remove(Object key, Object value)
* 指定された値に指定されたキー＋値が現在マッピングされている場合にのみ、そのキーのエントリを削除します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);

// キー＋値がある場合、削除される
map.get("JPN").remove("TOKYO",100);
System.out.println(map);

// キー＋値がない場合、削除されない
map.get("JPN").remove("OSAKA",100);
System.out.println(map);
```

```java
{JPN={OSAKA=200}}
{JPN={OSAKA=200}}
```

## 3.12. default boolean replace(K key, V value)
* 指定されたキーが指定された値に現在マッピングされている場合にのみ、そのキーのエントリを置換します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);

// キーがある場合、置換される
map.get("JPN").replace("TOKYO",200);
System.out.println(map);

// キーがない場合、置換されない
map.get("JPN").replace("NAGOYA",300);
System.out.println(map);
```

```java
{JPN={TOKYO=200, OSAKA=200}}
{JPN={TOKYO=200, OSAKA=200}}
```

## 3.13. default boolean replace(K key, V oldValue, V newValue)
* 指定されたキー＋値が指定された値に現在マッピングされている場合にのみ、そのキーのエントリを置換します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);

// キー＋値がある場合、置換される
map.get("JPN").replace("TOKYO", 100, 300);
System.out.println(map);

// キー＋値がない場合、置換されない
map.get("JPN").replace("OSAKA", 100, 300 );
System.out.println(map);
```

```java
{JPN={TOKYO=300, OSAKA=200}}
{JPN={TOKYO=300, OSAKA=200}}
```

## 3.14. boolean isEmpty()
* このマップがキーと値のマッピングを保持しない場合にtrueを返します。

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);
map.put("USA", new HashMap<String,Integer>());

// キー＋値がある場合、trueを返却する
System.out.println(map.get("JPN").isEmpty());

// キー＋値がない場合、falseを返却する
System.out.println(map.get("USA").isEmpty());

// Map自体がない場合、NullPointExceptionで例外が発生する
System.out.println(map.get("CHN").isEmpty());
```

```java
false
true
java.lang.NullPointerException
```

# 4. MapのKeySetのソート例
* Java7とJava8でKeySetで返却される並び順が違うため、一度配列にしてソートをする必要がある

https://qiita.com/70_10/items/8008d1963962cd81cc97

```java
Map<String, Map<String,Integer>> map = new HashMap<String, Map<String,Integer>>();
map.put("JPN", new HashMap<String,Integer>());
map.get("JPN").put("TOKYO", 100);
map.get("JPN").put("OSAKA", 200);

// 配列で取得
String[] keyArray = map.get("JPN").keySet().toArray(new String[map.get("JPN").size()]);

// 降順の場合
Arrays.sort(keyArray, Collections.reverseOrder());

// 昇順の場合
Arrays.sort(keyArray);

// 結果確認
for (String key : keyArray) {
    System.out.println(key);
}
```

```java
OSAKA
TOKYO
```

# 5. 参考文献

https://docs.oracle.com/javase/jp/8/docs/api/java/util/Map.html

https://qiita.com/wataru908/items/6c014321cf4b8496152e

https://qiita.com/DQMerA/items/965cd6462e1795e0d1a3

https://qiita.com/70_10/items/8008d1963962cd81cc97