天天看點

Map<Integer,Value>放入緩存後取出來變成了Map<String,Value>

背景

将一個類型為Map<Integer, String>的一個Map對象放到redis中後,再次取出來時。當我們想便利Map.entrySet()擷取每個Entry中的Key,如執行Integer key = entry.getKey();

那麼在執行時就會報錯:java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

Map<Integer,String> cacheMap =(Map<Integer,String>)redisCache.get(key);

for (Map.Entry<Integer, String> entry : cacheMap.entrySet()) {
    Integer key = entry.getKey();
    String value = entry.getValue();
}      

探究

debug時發現,在從redis獲得這個Map<Integer,String> cacheMap對象時,它其中的Key的實際類型已經是String類型。這是因為redisson采用JsonJacksonCodec反序列化時,是用Object作為對象decode。在這一步會預設把key設定成string。

private final Decoder<Object> decoder = new Decoder<Object>() {
        @Override
        public Object decode(ByteBuf buf, State state) throws IOException {
            return mapObjectMapper.readValue((InputStream) new ByteBufInputStream(buf), Object.class);
        }
    };      

測試

@Test
public void testMap() throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    HashMap<Integer, String> map = new HashMap<>();
    map.put(11, "little");
    map.put(6, "nuts");

    String s = mapper.writeValueAsString(map);
    //{"11":"little","6":"nuts"}
    System.out.println(s);

    HashMap o = (HashMap)mapper.readValue(s, Object.class);
    assertEquals(o.get("11"), "little");
    assertNotEquals(o.get(11), "little");
}      

總結

如果要針對,對象進行JsonJackson序列化時,如果對象是Map,則需要注意不要用Integer做為key。如果要将一個json對象作為redis緩存時,同樣不要将Integer當作HashMap的key類型。

本篇文章如有幫助到您,請給「翎野君」點個贊,感謝您的支援。

作者:翎野君

如果您喜歡或希望看到更多我的文章,可掃描二維碼關注我的微信公衆号《翎野君》。