JavaMap.getおよびMap.containsKey

JavaのMap実装を使用する場合、Map's get(Object)メソッドを呼び出し、返される値がnullであるかどうかに基づいて異なる反応をすることが一般的です。 Map.get(Object)から返されたnullは、マップに指定されたキーを持つエントリがないことを示すという一般的な仮定がなされる場合がありますが、常にそうであるとは限りません。実際、JavaMap実装でnull値が許可されMapている場合、は指定されたキーの値を返すことができますが、その値はnullである可能性があります。多くの場合、これは問題ではありませんが、問題がある場合は、Map.containsKey()を使用して、Mapエントリにキーエントリがあるかどうかを判断できます。その場合、同じキーのget呼び出しでMap戻る場合null、キーはにマップされている可能性があります。null値。言い換えれば、それがMapために「true」を返す可能性がありcontainsKey(Object)、同時に「戻しながらnullのために」get(Object)。値をMap許可しない実装がいくつかありnullます。そのような場合、null「get」呼び出しからのaは、「containsKey」メソッドからの「false」戻りと一貫して一致する必要があります。

このブログ記事では、私は、これらの側面を実証  Map.get(Object)してMap.containsKey(Object)。そのデモンストレーションに入る前に、Map.get(Object)のJavadocドキュメントがMap.get(Object)との微妙な違いについて明示的に警告していることを最初に指摘しますMap.containsKey(Object)

このマップでnull値が許可されている場合、の戻り値はnull 、マップにキーのマッピングが含まれていないことを必ずしも示しているわけではあり  ません。マップがキーをに明示的にマップすることも可能です  null。この  containsKey 操作は、これら2つのケースを区別するために使用できます。

投稿の例では、次に定義するStates列挙型を使用します。

States.java

package dustin.examples; /** * Enum representing select western states in the United Sates. */ public enum States { ARIZONA("Arizona"), CALIFORNIA("California"), COLORADO("Colorado"), IDAHO("Idaho"), KANSAS("Kansas"), MONTANA("Montana"), NEVADA("Nevada"), NEW_MEXICO("New Mexico"), NORTH_DAKOTA("North Dakota"), OREGON("Oregon"), SOUTH_DAKOTA("South Dakota"), UTAH("Utah"), WASHINGTON("Washington"), WYOMING("Wyoming"); /** State name. */ private String stateName; /** * Parameterized enum constructor accepting a state name. * * @param newStateName Name of the state. */ States(final String newStateName) { this.stateName = newStateName; } /** * Provide the name of the state. * * @return Name of the state */ public String getStateName() { return this.stateName; } } 

次のコードリストでは、上記の列挙型を使用して、州の地図を首都に入力します。このメソッドは、生成および設定されるMapの特定の実装である必要があるクラスを受け入れます。

generateStatesMap(Class)

/** * Generate and populate a Map of states to capitals with provided Map type. * This method also logs any Map implementations for which null values are * not allowed. * * @param mapClass Type of Map to be generated. * @return Map of states to capitals. */ private static Map generateStatesMap(Class mapClass) { Map mapToPopulate = null; if (Map.class.isAssignableFrom(mapClass)) { try { mapToPopulate = mapClass != EnumMap.class ? (Map) mapClass.newInstance() : getEnumMap(); mapToPopulate.put(States.ARIZONA, "Phoenix"); mapToPopulate.put(States.CALIFORNIA, "Sacramento"); mapToPopulate.put(States.COLORADO, "Denver"); mapToPopulate.put(States.IDAHO, "Boise"); mapToPopulate.put(States.NEVADA, "Carson City"); mapToPopulate.put(States.NEW_MEXICO, "Sante Fe"); mapToPopulate.put(States.NORTH_DAKOTA, "Bismark"); mapToPopulate.put(States.OREGON, "Salem"); mapToPopulate.put(States.SOUTH_DAKOTA, "Pierre"); mapToPopulate.put(States.UTAH, "Salt Lake City"); mapToPopulate.put(States.WASHINGTON, "Olympia"); mapToPopulate.put(States.WYOMING, "Cheyenne"); try { mapToPopulate.put(States.MONTANA, null); } catch (NullPointerException npe) { LOGGER.severe( mapToPopulate.getClass().getCanonicalName() + " does not allow for null values - " + npe.toString()); } } catch (InstantiationException instantiationException) { LOGGER.log( Level.SEVERE, "Unable to instantiate Map of type " + mapClass.getName() + instantiationException.toString(), instantiationException); } catch (IllegalAccessException illegalAccessException) { LOGGER.log( Level.SEVERE, "Unable to access Map of type " + mapClass.getName() + illegalAccessException.toString(), illegalAccessException); } } else { LOGGER.warning("Provided data type " + mapClass.getName() + " is not a Map."); } return mapToPopulate; } 

上記の方法は、さまざまな種類のマップを生成するために使用できます。今はコードを示していませんが、私の例では、HashMap、LinkedHashMap、ConcurrentHashMap、およびEnumMapの4つの特定の実装を使用してこれらのマップを作成します。次に、これら4つの実装のそれぞれが、次にdemonstrateGetAndContains(Map)示すメソッドを介して実行されます。

demoGetAndContains(マップ)

/** * Demonstrate Map.get(States) and Map.containsKey(States). * * @param map Map upon which demonstration should be conducted. */ private static void demonstrateGetAndContains(final Map map) { final StringBuilder demoResults = new StringBuilder(); final String mapType = map.getClass().getCanonicalName(); final States montana = States.MONTANA; demoResults.append(NEW_LINE); demoResults.append( "Map of type " + mapType + " returns " + (map.get(montana)) + " for Map.get() using " + montana.getStateName()); demoResults.append(NEW_LINE); demoResults.append( "Map of type " + mapType + " returns " + (map.containsKey(montana)) + " for Map.containsKey() using " + montana.getStateName()); demoResults.append(NEW_LINE); final States kansas = States.KANSAS; demoResults.append( "Map of type " + mapType + " returns " + (map.get(kansas)) + " for Map.get() using " + kansas.getStateName()); demoResults.append(NEW_LINE); demoResults.append( "Map of type " + mapType + " returns " + (map.containsKey(kansas)) + " for Map.containsKey() using " + kansas.getStateName()); demoResults.append(NEW_LINE); LOGGER.info(demoResults.toString()); } 

このデモンストレーションでは、カンザスにエントリがまったくないように、モンタナの資本値がnullになるようにマップを意図的に設定しました。これは、の違いを証明するのに役立ちますMap.get(Object)Map.containsKey(Object)。すべてのMap実装タイプでnull値が許可されるわけではないため、try / catchブロック内に大文字なしでMontanaを配置する部分を囲みました。

コードを介して4種類のマップを実行した結果が次に表示されます。

Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet logMapInfo INFO: HashMap: {MONTANA=null, WASHINGTON=Olympia, ARIZONA=Phoenix, CALIFORNIA=Sacramento, WYOMING=Cheyenne, SOUTH_DAKOTA=Pierre, COLORADO=Denver, NEW_MEXICO=Sante Fe, NORTH_DAKOTA=Bismark, NEVADA=Carson City, OREGON=Salem, UTAH=Salt Lake City, IDAHO=Boise} Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet demonstrateGetAndContains INFO: Map of type java.util.HashMap returns null for Map.get() using Montana Map of type java.util.HashMap returns true for Map.containsKey() using Montana Map of type java.util.HashMap returns null for Map.get() using Kansas Map of type java.util.HashMap returns false for Map.containsKey() using Kansas Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet logMapInfo INFO: LinkedHashMap: {ARIZONA=Phoenix, CALIFORNIA=Sacramento, COLORADO=Denver, IDAHO=Boise, NEVADA=Carson City, NEW_MEXICO=Sante Fe, NORTH_DAKOTA=Bismark, OREGON=Salem, SOUTH_DAKOTA=Pierre, UTAH=Salt Lake City, WASHINGTON=Olympia, WYOMING=Cheyenne, MONTANA=null} Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet demonstrateGetAndContains INFO: Map of type java.util.LinkedHashMap returns null for Map.get() using Montana Map of type java.util.LinkedHashMap returns true for Map.containsKey() using Montana Map of type java.util.LinkedHashMap returns null for Map.get() using Kansas Map of type java.util.LinkedHashMap returns false for Map.containsKey() using Kansas Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet generateStatesMap SEVERE: java.util.concurrent.ConcurrentHashMap does not allow for null values - java.lang.NullPointerException Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet logMapInfo INFO: ConcurrentHashMap: {SOUTH_DAKOTA=Pierre, ARIZONA=Phoenix, WYOMING=Cheyenne, UTAH=Salt Lake City, OREGON=Salem, CALIFORNIA=Sacramento, IDAHO=Boise, NEW_MEXICO=Sante Fe, COLORADO=Denver, NORTH_DAKOTA=Bismark, WASHINGTON=Olympia, NEVADA=Carson City} Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet demonstrateGetAndContains INFO: Map of type java.util.concurrent.ConcurrentHashMap returns null for Map.get() using Montana Map of type java.util.concurrent.ConcurrentHashMap returns false for Map.containsKey() using Montana Map of type java.util.concurrent.ConcurrentHashMap returns null for Map.get() using Kansas Map of type java.util.concurrent.ConcurrentHashMap returns false for Map.containsKey() using Kansas Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet logMapInfo INFO: EnumMap: {ARIZONA=Phoenix, CALIFORNIA=Sacramento, COLORADO=Denver, IDAHO=Boise, MONTANA=null, NEVADA=Carson City, NEW_MEXICO=Sante Fe, NORTH_DAKOTA=Bismark, OREGON=Salem, SOUTH_DAKOTA=Pierre, UTAH=Salt Lake City, WASHINGTON=Olympia, WYOMING=Cheyenne} Aug 17, 2010 11:23:26 PM dustin.examples.MapContainsGet demonstrateGetAndContains INFO: Map of type java.util.EnumMap returns null for Map.get() using Montana Map of type java.util.EnumMap returns true for Map.containsKey() using Montana Map of type java.util.EnumMap returns null for Map.get() using Kansas Map of type java.util.EnumMap returns false for Map.containsKey() using Kansas 

null値を入力できた3つのマップタイプの場合、モンタナに対してcontainsKey(Object)メソッドが「true」を返した場合でもMap.get(Object)呼び出しはnullを返します。これは、そのキーをマップに配置しなかったためです。値。カンザスの場合、結果は一貫してMap.get()がnullを返し、Map.containsKey()が「false」を返します。これは、カンザスのマップにエントリがまったくないためです。

上記の出力は、モンタナの首都のnull値をConcurrentHashMap実装に入れることができなかったことも示しています(NullPointerExceptionがスローされました)。

2010年8月17日午後11時23分26秒dustin.examples.MapContainsGetgenerateStatesMapSEVERE:java.util.concurrent.ConcurrentHashMapはnull値を許可しません-java.lang.NullPointerException

これには、それぞれのnullとfalseの戻り値を維持するという副作用がMap.get(Object)ありましMap.containsKey(Object)た。つまり、対応するnull以外の値がないと、キーをマップに含めることはできませんでした。

多くの場合の、使用Map.get(Object)手元の特定のニーズに合わせて必要に応じて動作しますが、それは間に違いがあることを覚えておくことが最善であるMap.get(Object)Map.containsKey(Object)確認してください適切なものが常に使用されていることを確認します。Mapにも同様のcontainsValue(Object)方法があることに注意してください。

完全を期すために、MapContainsGetクラスのコードリスト全体をここにリストします。

MapContainsGet.java