Redis缓存,泛型集合与json字符串的相互转换实例
作者:一只咸鱼的自我修养 发布时间:2021-07-18 16:57:15
难点是泛型如何转换
一、arrayList<Map<String, Object>>转化json字符串,存入redis缓存
ArrayList<Map<String, Object>> listProfit
//将ArrayList<Map<String, Object>>类型数据转换成json字符串
String listProfitPctJsonStr = JSON.toJSONString(listProfit);
//然后将json字符串存入redis缓存,唯一key value
JedisUtils.setex("listProfit", 600,listProfitPctJsonStr);
二、json字符串转回ArrayList<Map<String, Object>>(难点)
List<Map<String, Object>> listProfit=null;
//先从redis里面去查询数据,看是否能获取到对应json字符串
String jsonStrLp=JedisUtils.get("listProfit");
//如果能获取则说明缓存中有数据
if(!StringUtils.isBlank(jsonStrLp)){
//目的是为了泛型的转换
listProfit=new ArrayList<Map<String,Object>>();
//先把从redis缓存中取出来的json字符串转为List<Map>集合
List<Map> mapList=JSON.parseArray(jsonStrLp, Map.class);
//然后循环遍历这个List集合,得出的结果为Map,然后再强转为Map<String,Object>,
再循环 把 Map<String,Object>添加到List集合中,搞定!!!
for (Map map : mapList) {
Map<String,Object> sObj=(Map<String,Object>)map;
listProfit.add(sObj);
}
补充知识:Java的List和Json转换以及StringRedisTemplate往redis存泛型对象
List转Json
List<User> user= new ArrayList();
String str = JSON.toJSONString(user);
Json 转List方法一
List<User> user= JSON.parseArray(json,User.class);
如果是泛型方法需要使用TypeReference
Json 转List 方法二
String json = "[{}]";
List<user> user= JSON.parseObject(json,new TypeReference<List<User>>(){});
泛型T
Json 转List方法三
List<T> students = JSON.parseObject(listCache,new TypeReference<List<T>>(){});
综合例子:Springboot环境下利用StringRedisTemplate往redis存泛型对象
一开始要注入下StringRedisTemplate
@Autowired
private StringRedisTemplate redisTemplate;
Redis获取值不存在就从数据库取出来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]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
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]);
}
// 如果有多层泛型且该泛型已经注明实现的情况下,判断该泛型下一层是否还有泛型
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(); //返回泛型类型数组
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;
// 使用反射技术得到T的真实类型
public Class getRealType(){
Class c=this.getClass();
//getSuperclass()获得该类的父类
System.out.println("getSuperclass >>>"+c.getSuperclass());
//getGenericSuperclass()获得带有泛型的父类
System.out.println("getGenericSuperclass >>>"+c.getGenericSuperclass());
//Type是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
Type type=c.getGenericSuperclass();
System.out.println("Type >>>"+type);
//ParameterizedType参数化类型,即泛型
// 获取当前new的对象的泛型的父类类型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
// 获取第一个类型参数的真实类型
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());
}
}
来源:https://blog.csdn.net/weixin_40671802/article/details/79426243
猜你喜欢
- 本文实例展示了WinForm实现为TextBox设置水印文字功能,非常实用的技巧,分享给大家供大家参考。关键代码如下:using Syste
- 1. 开方:Math.sqrt(x);2. x的a方:Math.pow(x,a);3. 绝对值:Math.abs(x);4. BigInte
- 一、简介构造函数,基本用法是在类对象声明的时候完成初始化工作。二、实例构造函数1、构造函数的名字与类名相同。2、使用 new 表达式创建类的
- 以下代码实现了android的免提开启和关闭功能需要添加的权限<uses-permission android:name="
- android中提供了4中动画: AlphaAnimation 透明度动画效果 ScaleAnimation 缩放动画效果 Translat
- 1.为什么要使用synchronized在并发编程中存在线程安全问题,主要原因有:1.存在共享数据 2.多线程共同操作共享数据。关键字syn
- 本节我们基于一个发表文章的案例来说明SpringBoot如何elasticsearch集成。elasticsearch本身可以是一个独立的服
- 判断对象存活方法引用计数法:在对象中添加一个引用计数子,每当一个地方引用他时,计数器就加一,当引用失效时,计数器就减一。会有对象循环引用问题
- 记录Java执行groovy脚本的两种方式,简单粗暴:一种是通过脚本引擎ScriptEngine提供的eval(String)方法执行脚本内
- 本文实例为大家分享了java实现文件上传下载的具体代码,供大家参考,具体内容如下1.上传单个文件Controller控制层import ja
- 本文实例为大家分享了Android实现画板的具体代码,采用的技术是双缓冲技术,供大家参考,具体内容如下1.双缓冲技术的概念所谓的双缓冲技术其
- WPF 使用 DrawingContext 绘制刻度条框架使用大于等于.NET40;Visual Studio 2022;项目使用 
- “反射”其实就是利用程序集的元数据信息。 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间。1、假设你要
- 前言一般数据库的表结构都会有update_time,修改时间,因为这个字段基本与业务没有太大关联,因此开发过程中经常会忘记设置这两个字段的值
- Android 中RecycleView实现item的点击事件RecycleView现在已经越来越受到大家的重视,因为他既可以代替listV
- 前言在前后端分离开发的时候我们需要用到参数校验,前端需要进行参数校验,后端接口同样的也需要,以防传入不合法的数据。1、首先还是先导包,导入p
- name和value属性的区别从源码可以得知,name是value的别名,value也是name的别名。两者的作用是一致的,name指定Fe
- 题目题目背景若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。思路对
- 本文实例为大家分享了Android检测手机多点触摸点数的具体代码,供大家参考,具体内容如下多点触摸点数效果图Circle.javapacka
- 当setCanceledOnTouchOutside(true),点击阴影处,dialog dismiss时键盘不消失的问题。如图一开始觉得