Redis緩存,泛型集合與json字符串的相互轉(zhuǎn)換實例
難點是泛型如何轉(zhuǎn)換
一、arrayList<Map<String, Object>>轉(zhuǎn)化json字符串,存入redis緩存
ArrayList<Map<String, Object>> listProfit //將ArrayList<Map<String, Object>>類型數(shù)據(jù)轉(zhuǎn)換成json字符串 String listProfitPctJsonStr = JSON.toJSONString(listProfit); //然后將json字符串存入redis緩存,唯一key value JedisUtils.setex("listProfit", 600,listProfitPctJsonStr);
二、json字符串轉(zhuǎn)回ArrayList<Map<String, Object>>(難點)
List<Map<String, Object>> listProfit=null; //先從redis里面去查詢數(shù)據(jù),看是否能獲取到對應json字符串 String jsonStrLp=JedisUtils.get("listProfit"); //如果能獲取則說明緩存中有數(shù)據(jù) if(!StringUtils.isBlank(jsonStrLp)){ //目的是為了泛型的轉(zhuǎn)換 listProfit=new ArrayList<Map<String,Object>>(); //先把從redis緩存中取出來的json字符串轉(zhuǎn)為List<Map>集合 List<Map> mapList=JSON.parseArray(jsonStrLp, Map.class); //然后循環(huán)遍歷這個List集合,得出的結(jié)果為Map,然后再強轉(zhuǎn)為Map<String,Object>, 再循環(huán) 把 Map<String,Object>添加到List集合中,搞定?。。? for (Map map : mapList) { Map<String,Object> sObj=(Map<String,Object>)map; listProfit.add(sObj); }
補充知識:Java的List和Json轉(zhuǎn)換以及StringRedisTemplate往redis存泛型對象
List轉(zhuǎn)Json
List<User> user= new ArrayList();
String str = JSON.toJSONString(user);
Json 轉(zhuǎn)List方法一
List<User> user= JSON.parseArray(json,User.class);
如果是泛型方法需要使用TypeReference
Json 轉(zhuǎn)List 方法二
String json = "[{}]";
List<user> user= JSON.parseObject(json,new TypeReference<List<User>>(){});
泛型T
Json 轉(zhuǎn)List方法三
List<T> students = JSON.parseObject(listCache,new TypeReference<List<T>>(){});
綜合例子:Springboot環(huán)境下利用StringRedisTemplate往redis存泛型對象
一開始要注入下StringRedisTemplate
@Autowired
private StringRedisTemplate redisTemplate;
Redis獲取值不存在就從數(shù)據(jù)庫取出來json化存緩存,存在則直接反序列化json為List
List<T> list; String listCache=redisTemplate.opsForValue().get(key); if(listCache!=null){ list = JSON.parseObject(listCache,new TypeReference<List<T>>(){}); } else { list = userService.getAllList(); redisTemplate.opsForValue().set(key, JSON.toJSONString(list), 60 * 1, TimeUnit.SECONDS); }
附錄:TypeReference源碼
package com.alibaba.fastjson; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.alibaba.fastjson.util.ParameterizedTypeImpl; import com.alibaba.fastjson.util.TypeUtils; /** * Represents a generic type {@code T}. Java doesn't yet provide a way to * represent generic types, so this class does. Forces clients to create a * subclass of this class which enables retrieval the type information even at * runtime. * * <p>For example, to create a type literal for {@code List<String>}, you can * create an empty anonymous inner class: * * <pre> * TypeReference<List<String>> list = new TypeReference<List<String>>() {}; * </pre> * This syntax cannot be used to create type literals that have wildcard * parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}. */ public class TypeReference<T> { static ConcurrentMap<Type, Type> classTypeCache = new ConcurrentHashMap<Type, Type>(16, 0.75f, 1); protected final Type type; /** * Constructs a new type literal. Derives represented class from type * parameter. * * <p>Clients create an empty anonymous subclass. Doing so embeds the type * parameter in the anonymous class's type hierarchy so we can reconstitute it * at runtime despite erasure. */ protected TypeReference(){ Type superClass = getClass().getGenericSuperclass(); Type type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; Type cachedType = classTypeCache.get(type); if (cachedType == null) { classTypeCache.putIfAbsent(type, type); cachedType = classTypeCache.get(type); } this.type = cachedType; } /** * @since 1.2.9 * @param actualTypeArguments */ protected TypeReference(Type... actualTypeArguments){ Class<?> thisClass = this.getClass(); Type superClass = thisClass.getGenericSuperclass(); ParameterizedType argType = (ParameterizedType) ((ParameterizedType) superClass).getActualTypeArguments()[0]; Type rawType = argType.getRawType(); Type[] argTypes = argType.getActualTypeArguments(); int actualIndex = 0; for (int i = 0; i < argTypes.length; ++i) { if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) { argTypes[i] = actualTypeArguments[actualIndex++]; } // fix for openjdk and android env if (argTypes[i] instanceof GenericArrayType) { argTypes[i] = TypeUtils.checkPrimitiveArray( (GenericArrayType) argTypes[i]); } // 如果有多層泛型且該泛型已經(jīng)注明實現(xiàn)的情況下,判斷該泛型下一層是否還有泛型 if(argTypes[i] instanceof ParameterizedType) { argTypes[i] = handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex); } } Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType); Type cachedType = classTypeCache.get(key); if (cachedType == null) { classTypeCache.putIfAbsent(key, key); cachedType = classTypeCache.get(key); } type = cachedType; } private Type handlerParameterizedType(ParameterizedType type, Type[] actualTypeArguments, int actualIndex) { Class<?> thisClass = this.getClass(); Type rawType = type.getRawType(); Type[] argTypes = type.getActualTypeArguments(); for(int i = 0; i < argTypes.length; ++i) { if (argTypes[i] instanceof TypeVariable && actualIndex < actualTypeArguments.length) { argTypes[i] = actualTypeArguments[actualIndex++]; } // fix for openjdk and android env if (argTypes[i] instanceof GenericArrayType) { argTypes[i] = TypeUtils.checkPrimitiveArray( (GenericArrayType) argTypes[i]); } // 如果有多層泛型且該泛型已經(jīng)注明實現(xiàn)的情況下,判斷該泛型下一層是否還有泛型 if(argTypes[i] instanceof ParameterizedType) { return handlerParameterizedType((ParameterizedType) argTypes[i], actualTypeArguments, actualIndex); } } Type key = new ParameterizedTypeImpl(argTypes, thisClass, rawType); return key; } /** * Gets underlying {@code Type} instance. */ public Type getType() { return type; } public final static Type LIST_STRING = new TypeReference<List<String>>() {}.getType(); }
TypeReference的存在是因為java中子類可以獲取到父類泛型的真實類型。
其中核心的方法是:getActualTypeArguments,它可以得到父類的反省類型
ParameterizedType是一個記錄類型泛型的接口, 繼承自Type,一共三方法:
Type[] getActualTypeArguments(); //返回泛型類型數(shù)組 Type getRawType(); //返回原始類型Type Type getOwnerType(); //返回 Type 對象,表示此類型是其成員之一的類型。
Map<String, Integer> intMap = new HashMap<>(); System.out.println("getSuperclass:" + intMap.getClass().getSuperclass()); System.out.println("getGenericSuperclass:" + intMap.getClass().getGenericSuperclass()); Type type = intMap.getClass().getGenericSuperclass(); if (type instanceof ParameterizedType) { ParameterizedType p = (ParameterizedType)type; for (Type t : p.getActualTypeArguments()) { System.out.println("getActualTypeArguments>>>"+t); } }
擴展閱讀Java如何獲得泛型類的真實類型:
package com.paopaoedu.springboot.demo; import com.paopaoedu.springboot.bean.User; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public class BaseDao<T>{ private Class<T> clazz; // 使用反射技術(shù)得到T的真實類型 public Class getRealType(){ Class c=this.getClass(); //getSuperclass()獲得該類的父類 System.out.println("getSuperclass >>>"+c.getSuperclass()); //getGenericSuperclass()獲得帶有泛型的父類 System.out.println("getGenericSuperclass >>>"+c.getGenericSuperclass()); //Type是 Java 編程語言中所有類型的公共高級接口。它們包括原始類型、參數(shù)化類型、數(shù)組類型、類型變量和基本類型。 Type type=c.getGenericSuperclass(); System.out.println("Type >>>"+type); //ParameterizedType參數(shù)化類型,即泛型 // 獲取當前new的對象的泛型的父類類型 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 獲取第一個類型參數(shù)的真實類型 this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; c=(Class) pt.getActualTypeArguments()[0]; System.out.println(c); return clazz; } } class userdemo extends BaseDao<User>{ public static void main(String[] args) { userdemo classB = new userdemo(); Class realType = classB.getRealType(); System.out.println(realType.getName()); } }
以上這篇Redis緩存,泛型集合與json字符串的相互轉(zhuǎn)換實例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java 帶參數(shù)與帶返回值的方法的定義和調(diào)用
在java中,方法就是用來完成解決某件事情或?qū)崿F(xiàn)某個功能的辦法。方法實現(xiàn)的過程中,會包含很多條語句用于完成某些有意義的功能——通常是處理文本,控制輸入或計算數(shù)值,這篇文章我們來探究一下帶參數(shù)與帶返回值的方法的定義和調(diào)用2022-04-04java數(shù)據(jù)結(jié)構(gòu)之二分查找法 binarySearch的實例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)之二分查找法 binarySearch的實例的相關(guān)資料,希望通過本文能幫助到大家,讓大家理解掌握這部分內(nèi)容,需要的朋友可以參考下2017-10-10Spring boot中PropertySource注解的使用方法詳解
這篇文章主要給大家介紹了關(guān)于Spring boot中PropertySource注解的使用方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧。2017-12-12java 方法重寫與權(quán)限修飾符以及多態(tài)和抽象類詳解概念和用法
重寫是子類對父類的允許訪問的方法的實現(xiàn)過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫,權(quán)限修飾符用于控制被修飾變量、方法、類的可見范圍,說明了面向?qū)ο蟮姆庋b性,所以我們要適用他們盡可能的讓權(quán)限降到最低,從而安全性提高2021-10-10