Programování

Java Map.get a Map.containsKey

Při použití implementací Java Map je někdy běžné vyvolat MapaMetoda get (Object) a reagovat odlišně na základě toho, zda je vrácená hodnota null nebo ne. Je možné vytvořit společný předpoklad, že hodnota null vrácená z Map.get (Object) naznačuje, že v mapě není žádná položka s poskytnutým klíčem, ale není tomu tak vždy. Opravdu, pokud Java Mapa implementace umožňuje nulové hodnoty, pak je možné pro Mapa vrátit jeho hodnotu pro daný klíč, ale tato hodnota může mít hodnotu null. Často to nevadí, ale pokud ano, lze pomocí Map.containsKey () určit, zda Mapa záznam má klíčový záznam. Pokud ano, a Mapa se vrací nula při volání volání pro stejný klíč, pak je pravděpodobné, že se klíč mapuje na a nula hodnota. Jinými slovy, to Mapa se může vrátit „true“ pro containsKey (Object) zároveň se vracet “ nula" pro get (Object). Tam jsou nějací Mapa implementace, které to neumožňují nula hodnoty. V těchto případech a nula z volání „get“ by se mělo důsledně shodovat s „false“ návratem z metody „containsKey“.

V tomto příspěvku na blogu ukazuji tyto aspekty Map.get (objekt) a Map.containsKey (objekt). Než se pustím do této demonstrace, nejprve zdůrazním, že dokumentace Javadoc pro Map.get (Object) výslovně varuje před jemnými rozdíly mezi Map.get (objekt) a Map.containsKey (objekt):

Pokud tato mapa umožňuje nulové hodnoty, pak návratová hodnota nula nemusí nutně znamenat, že mapa neobsahuje žádné mapování klíče; je také možné, že mapa explicitně mapuje klíč nula. The containsKey operaci lze použít k rozlišení těchto dvou případů.

Pro příklady příspěvku budu používat dále uvedený States enum definovaný:

Státy.java

příklady zásilky; / ** * Enum představující vybrané západní státy ve Spojených státech. * / public enum Státy {ARIZONA („Arizona“), CALIFORNIA („Kalifornie“), COLORADO („Colorado“), IDAHO („Idaho“), KANSAS („Kansas“), MONTANA („Montana“), NEVADA ( „Nevada“), NEW_MEXICO („Nové Mexiko“), NORTH_DAKOTA („Severní Dakota“), OREGON („Oregon“), SOUTH_DAKOTA („Jižní Dakota“), UTAH („Utah“), WASHINGTON („Washington“), WYOMING („Wyoming“); / ** Název státu. * / private String stateName; / ** * Parametrizovaný konstruktér výčtu přijímající název státu. * * @param newStateName Název státu. * / States (konečný řetězec newStateName) {this.stateName = newStateName; } / ** * Uveďte název státu. * * @return Název státu * / public String getStateName () {return this.stateName; }} 

Následující výpis kódu používá výše uvedený výčet a naplní mapu států do jejich hlavních měst. Metoda přijímá třídu, která by měla být konkrétní implementací Map, která má být generována a naplněna.

generateStatesMap (třída)

/ ** * Vytvoří a naplní mapu států na velká písmena zadaným typem mapy. * Tato metoda také zaznamenává všechny implementace Map, pro které nejsou povoleny nulové hodnoty. * * @param mapClass Typ mapy, která má být vygenerována. * @return Mapa států na hlavní města. * / private static Map generateStatesMap (Class mapClass) {Map mapToPopulate = null; if (Map.class.isAssignableFrom (mapClass)) {try {mapToPopulate = mapClass! = EnumMap.class? (Mapa) 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, "Čejen"); try {mapToPopulate.put (States.MONTANA, null); } catch (NullPointerException npe) {LOGGER.severe (mapToPopulate.getClass (). getCanonicalName () + "neumožňuje hodnoty null -" + npe.toString ()); }} catch (InstantiationException instantiationException) {LOGGER.log (Level.SEVERE, "Nelze vytvořit instanci Mapy typu" + mapClass.getName () + instantiationException.toString (), instantiationException); } catch (IllegalAccessException legalAccessException) {LOGGER.log (Level.SEVERE, "Nelze získat přístup k Mapě typu" + mapClass.getName () + nelegálníAccessException.toString (), nelegálníAccessException); }} else {LOGGER.warning ("Poskytovaný datový typ" + mapClass.getName () + "není Mapa."); } vrátit mapToPopulate; } 

Výše uvedenou metodu lze použít ke generování map různých druhů. Momentálně kód neukazuji, ale můj příklad vytváří tyto Mapy se čtyřmi konkrétními implementacemi: HashMap, LinkedHashMap, ConcurrentHashMap a EnumMap. Každá z těchto čtyř implementací je poté spuštěna metodou demonstrovatGetAndContains (mapa), který je zobrazen dále.

demonstrovatGetAndContains (mapa)

/ ** * Předveďte Map.get (státy) a Map.containsKey (státy). * * @param map Mapa, na které by měla být provedena demonstrace. * / private static void proveďte ukázkuGetAndContains (konečná mapa mapy) {final StringBuilder demoResults = new StringBuilder (); final String mapType = map.getClass (). getCanonicalName (); final States montana = States.MONTANA; demoResults.append (NEW_LINE); demoResults.append ("Mapa typu" + mapType + "vrací" + (map.get (montana)) + "pro Map.get () pomocí" + montana.getStateName ()); demoResults.append (NEW_LINE); demoResults.append ("Mapa typu" + mapType + "vrací" + (map.containsKey (montana)) + "pro Map.containsKey () pomocí" + montana.getStateName ()); demoResults.append (NEW_LINE); konečné státy kansas = státy.KANSAS; demoResults.append ("Mapa typu" + mapType + "vrací" + (map.get (kansas)) + "pro Map.get () pomocí" + kansas.getStateName ()); demoResults.append (NEW_LINE); demoResults.append ("Mapa typu" + mapType + "vrací" + (map.containsKey (kansas)) + "pro Map.containsKey () pomocí" + kansas.getStateName ()); demoResults.append (NEW_LINE); LOGGER.info (demoResults.toString ()); } 

Pro tuto demonstraci jsem záměrně nastavil Mapy tak, aby měly nulové kapitálové hodnoty pro Montanu, aby pro Kansas neměly vůbec žádný vstup. To pomáhá demonstrovat rozdíly v Map.get (objekt) a Map.containsKey (objekt). Protože ne každý typ implementace Map umožňuje nulové hodnoty, obklopil jsem část, která staví Montanu bez kapitálu uvnitř bloku try / catch.

Dále se zobrazí výsledky spuštění čtyř typů Map prostřednictvím kódu.

17. srpna 2010 23:23:26 dustin.examples.MapContainsGet logMapInfo INFO: HashMap: {MONTANA = null, WASHINGTON = Olympia, ARIZONA = Phoenix, CALIFORNIA = Sacramento, WYOMING = Cheyenne, SOUTH_DAKOTA = Pierre, COLORADO = Den, COLORADO = Den = Sante Fe, NORTH_DAKOTA = Bismark, NEVADA = Carson City, OREGON = Salem, UTAH = Salt Lake City, IDAHO = Boise} 17. srpna 2010 23:23:26 dustin.examples.MapContainsGet demonstrovatGetAndContains INFO: Mapa typu java. util.HashMap vrátí null pro Map.get () pomocí Montana Map typu java.util.HashMap vrátí true pro Map.containsKey () pomocí Montana Map typu java.util.HashMap vrátí null pro Map.get () pomocí Kansas Map typu java.util.HashMap vrací false pro Map.containsKey () pomocí Kansasu 17. srpna 2010 23:23:26 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} 17. srpna 2010 23:23:26 dustin.examples.MapContainsGet demonstrovatGetAndContains INFO: Mapa typu java.util.LinkedHashMap vrací null pro Map.get () pomocí Montana Mapa typu java .util.LinkedHashMap vrací true pro Map.containsKey () pomocí Montana Map typu java.util.LinkedHashMap vrací null pro Map.get () pomocí Kansasu Mapa typu java.util.LinkedHashMap vrací false pro Map.containsKey () pomocí Kansasu 17. srpna 2010 23:23:26 dustin.examples.MapContainsGet generateStatesMap SEVERE: java.util.concurrent.ConcurrentHashMap neumožňuje nulové hodnoty - java.lang.NullPointerException 17. srpna 2010 23:23:26 dustin.examples .MapContainsZískejte logMapInfo INFO: ConcurrentHashMap: {SOUTH_DAKOTA = Pierre, ARIZONA = Phoenix, WYOMING = Cheyenne, UTAH = Salt Lake City, OREGON = Salem, CALIFORNIA = Sacramento, IDAHO = Boise, NEW_MEXICO = Sante FeD, COLORO = BARVA , WASHINGTON = Olympia, NEVADA = Carson City} 17. srpna 2010 23:23:26 dustin.examples.Ma pContainsGet demonstrovatGetAndContains INFO: Mapa typu java.util.concurrent.ConcurrentHashMap vrací null pro Map.get () pomocí Montana Mapa typu java.util.concurrent.ConcurrentHashMap vrací false pro Map.containsKey () pomocí Montana Map typu java.util .concurrent.ConcurrentHashMap vrací null pro Map.get () pomocí Kansas Map typu java.util.concurrent.ConcurrentHashMap vrací false pro Map.containsKey () pomocí Kansasu 17. srpna 2010 23:23:26 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, UUT Lake City, WASHINGTON = Olympia, WYOMING = Cheyenne} 17. srpna 2010 23:23:26 dustin.examples.MapContainsGet demonstrovatGetAndContains INFO: Mapa typu java.util.EnumMap vrací null pro Map.get () pomocí Montana Mapa typu java.util.EnumMap vrací true pro Map.containsKey () pomocí Montana Map of ty pe java.util.EnumMap vrací null pro Map.get () pomocí Kansasu Mapa typu java.util.EnumMap vrací false pro Map.containsKey () pomocí Kansasu 

U tří typů Map, pro které jsem byl schopen zadat hodnoty null, volání Map.get (Object) vrací null, i když metoda containsKey (Object) vrací „true“ pro Montanu, protože jsem tento klíč vložil do mapy bez hodnota. Pro Kansas jsou výsledky důsledně Map.get () vrací null a Map.containsKey () vrací „false“, protože v Mapách pro Kansas není vůbec žádný záznam.

Výše uvedený výstup také ukazuje, že jsem nemohl dát nulovou hodnotu pro kapitál Montany do ConcurrentHashMap implementace (byla vyvolána NullPointerException).

17. srpna 2010 23:23:26 dustin.examples.MapContainsGet generateStatesMapSEVERE: java.util.concurrent.ConcurrentHashMap neumožňuje nulové hodnoty - java.lang.NullPointerException

To mělo vedlejší účinek zachování Map.get (objekt) a Map.containsKey (objekt) konzistentnější příslušné nulové a falešné návratové hodnoty. Jinými slovy, bylo nemožné mít na mapě klíč, aniž bychom měli odpovídající nenulovou hodnotu.

V mnoha případech použití Map.get (objekt) funguje podle potřeby pro konkrétní konkrétní potřeby, ale je nejlepší si uvědomit, že existují rozdíly mezi nimi Map.get (objekt) a Map.containsKey (objekt) abyste se ujistili, že je vždy použit vhodný. Je také zajímavé si povšimnout, že Map má podobné containsValue (Object) metoda také.

Uvádím zde celý seznam kódů pro třídu MapContainsGet pro úplnost:

MapContainsGet.java

$config[zx-auto] not found$config[zx-overlay] not found