Spring redisTemplate.opsForValue().get() 返回List <LinkedHashMap>而不是String类型

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.XXX.XXX.xxClass

存入redis时是这样存的

List<Oa> value; 是一个list
redisTemplate.opsForValue().set( key, value);

从redis中取出数据

oldList = (List<T>) redisTemplate.opsForValue().get(key);

发生如下错误

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.XXX.XXX.OaClass 

原因是可能是

在将字符串转换为对象列表时没有指定特定类型,该对象是具有通用类型的类,例如List<T>
或者是redis的版本不对,当我使用开发环境和测设环境进行转换时,并没有发生以上情况,
而在生产环境确发生了

最后的解决方案是使用阿里的fastjson进行转换

oldList = (List<T>) redisTemplate.opsForValue().get(redisKey + wxId);
String jsonList = JSON.toJSONString(oldList);
oldList = JSON.parseArray(jsonList, clazz);
package com.hangcheng.website.util; import cn.hutool.core.collection.CollectionUtil; import com.hangcheng.website.config.CourseConfig; import com.hangcheng.website.domain.response.ComboResult; import com.hangcheng.website.domain.response.ComboVoResult; import com.hangcheng.website.domain.response.CourseIntelligentPageResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.*; import java.util.stream.Collectors; /** * @ClassName : CourseSelectUtils * @Description : 课程智能组合工具类 - 针对200课程10组合优化版 * @Author : 牛欣如 * @Date: 2025-09-02 14:10 */ @Component public class CourseSelectUtils { @Autowired private CourseConfig courseConfig; private static final int MAX_COURSES_PER_COMBO = 10; private static final int MAX_COMBINATIONS_PER_GROUP = 10; private static final int MAX_TOTAL_COURSES = 200; /** * 为单个条件生成课程组合(优化版,专门针对200课程生成10个组合) */ public List<List<CourseIntelligentPageResponse>> generateNearestCombinations( int targetHours, int minCourses, int maxCourses, List<CourseIntelligentPageResponse> courses, int numCombinations) { // 过滤有效课程并排序(按学时降序,利于剪枝) List<CourseIntelligentPageResponse> validCourses = courses.stream() .limit(MAX_TOTAL_COURSES).collect(Collectors.toList()); // 根据数据规模选择合适的算法 List<List<CourseIntelligentPageResponse>> combinations; combinations = findCombinationsBacktrackOptimized(validCourses, targetHours, minCourses, maxCourses, numCombinations); // 排序:门数升序,相同时学时降序 combinations.sort((c1, c2) -> { int sizeCompare = Integer.compare(c1.size(), c2.size()); if (sizeCompare != 0) return sizeCompare; int sum1 = c1.stream().mapToInt(CourseIntelligentPageResponse::getHourCount).sum(); int sum2 = c2.stream().mapToInt(CourseIntelligentPageResponse::getHourCount).sum(); return Integer.compare(sum2, sum1); }); return getUniqueCombinations(combinations, numCombinations); } /** * 优化的回溯算法 */ private List<List<CourseIntelligentPageResponse>> findCombinationsBacktrackOptimized( List<CourseIntelligentPageResponse> courses, int targetHours, int minCourses, int maxCourses, int maxResults) { List<List<CourseIntelligentPageResponse>> result = new ArrayList<>(); Set<String> fingerprints = new HashSet<>(); // 按门数范围分别搜索 for (int courseCount = minCourses; courseCount <= maxCourses && result.size() < maxResults; courseCount++) { backtrackOptimized(courses, targetHours, courseCount, 0, new ArrayList<>(), result, fingerprints, maxResults); } return result; } /** * 强化的回溯剪枝算法 */ private void backtrackOptimized(List<CourseIntelligentPageResponse> courses, int target, int courseCount, int start, List<CourseIntelligentPageResponse> current, List<List<CourseIntelligentPageResponse>> result, Set<String> fingerprints, int maxResults) { if (result.size() >= maxResults) return; // 提前终止条件:当前总和已经超过目标 int currentSum = current.stream().mapToInt(CourseIntelligentPageResponse::getHourCount).sum(); if (currentSum > target) return; if (current.size() == courseCount) { if (currentSum == target) { String fingerprint = generateCombinationFingerprint(current); if (!fingerprints.contains(fingerprint)) { fingerprints.add(fingerprint); result.add(new ArrayList<>(current)); } } return; } // 计算剩余课程的最大可能和 int maxRemainingSum = 0; int remainingCourses = courseCount - current.size(); for (int i = start; i < Math.min(start + remainingCourses, courses.size()); i++) { maxRemainingSum += courses.get(i).getHourCount(); } // 强力剪枝 if (currentSum + maxRemainingSum < target) return; for (int i = start; i < courses.size() && result.size() < maxResults; i++) { CourseIntelligentPageResponse course = courses.get(i); // 剪枝:加上当前课程后超过目标 if (currentSum + course.getHourCount() > target) continue; // 剪枝:剩余位置不足 if (courses.size() - i < courseCount - current.size()) break; current.add(course); backtrackOptimized(courses, target, courseCount, i + 1, current, result, fingerprints, maxResults); current.remove(current.size() - 1); } } /** * 跨条件组合生成(优化版) */ public ComboVoResult generateOrderedCombinations( Map<String, List<List<CourseIntelligentPageResponse>>> groupCombinationsMap, int numCombinations) { ComboVoResult voResult = new ComboVoResult(); if (CollectionUtil.isEmpty(groupCombinationsMap)) { voResult.setResults(new ArrayList<>()); voResult.setFailGroupCourses(new ArrayList<>()); return voResult; } // 验证每个条件的组合数量 List<String> failGroups = groupCombinationsMap.entrySet().stream() .filter(entry -> CollectionUtil.isEmpty(entry.getValue())) .map(Map.Entry::getKey) .collect(Collectors.toList()); if (!failGroups.isEmpty()) { voResult.setResults(new ArrayList<>()); voResult.setFailGroupCourses(failGroups); return voResult; } // 限制每个条件的组合数量,避免组合爆炸 Map<String, List<List<CourseIntelligentPageResponse>>> limitedCombinationsMap = new HashMap<>(); groupCombinationsMap.forEach((key, combinations) -> { List<List<CourseIntelligentPageResponse>> limited = combinations.stream() .limit(MAX_COMBINATIONS_PER_GROUP) .collect(Collectors.toList()); limitedCombinationsMap.put(key, limited); }); // 使用DFS生成跨条件组合 List<ComboResult> results = generateCrossGroupCombinationsDFS(limitedCombinationsMap, numCombinations); voResult.setResults(results); voResult.setFailGroupCourses(new ArrayList<>()); // 前面已经验证过,没有失败组 return voResult; } /** * 使用DFS生成跨条件组合(避免重复课程) */ private List<ComboResult> generateCrossGroupCombinationsDFS( Map<String, List<List<CourseIntelligentPageResponse>>> groupCombinationsMap, int maxCombinations) { List<ComboResult> results = new ArrayList<>(); List<String> groupKeys = new ArrayList<>(groupCombinationsMap.keySet()); // 按组合数量升序排列,优先处理组合少的组(利于剪枝) groupKeys.sort((k1, k2) -> Integer.compare(groupCombinationsMap.get(k1).size(), groupCombinationsMap.get(k2).size())); dfsCrossGroups(groupCombinationsMap, groupKeys, 0, new LinkedHashMap<>(), new HashSet<>(), results, maxCombinations); return results; } /** * DFS递归生成跨组组合 */ private void dfsCrossGroups(Map<String, List<List<CourseIntelligentPageResponse>>> groupCombinationsMap, List<String> groupKeys, int currentIndex, Map<String, List<CourseIntelligentPageResponse>> currentSelection, Set<Long> usedCourseIds, List<ComboResult> results, int maxResults) { if (results.size() >= maxResults) return; if (currentIndex >= groupKeys.size()) { // 找到一个完整组合 ComboResult combo = new ComboResult(); combo.setGroupCourses(new LinkedHashMap<>(currentSelection)); results.add(combo); return; } String currentGroup = groupKeys.get(currentIndex); List<List<CourseIntelligentPageResponse>> combinations = groupCombinationsMap.get(currentGroup); for (List<CourseIntelligentPageResponse> combination : combinations) { // 检查课程是否重复 boolean hasConflict = false; Set<Long> newCourseIds = new HashSet<>(); for (CourseIntelligentPageResponse course : combination) { if (usedCourseIds.contains(course.getId())) { hasConflict = true; break; } newCourseIds.add(course.getId()); } if (hasConflict) continue; // 选择当前组合 usedCourseIds.addAll(newCourseIds); currentSelection.put(currentGroup, new ArrayList<>(combination)); // 递归下一个组 dfsCrossGroups(groupCombinationsMap, groupKeys, currentIndex + 1, currentSelection, usedCourseIds, results, maxResults); // 回溯 usedCourseIds.removeAll(newCourseIds); currentSelection.remove(currentGroup); if (results.size() >= maxResults) return; } } /** * 获取唯一组合 */ private List<List<CourseIntelligentPageResponse>> getUniqueCombinations( List<List<CourseIntelligentPageResponse>> allCombinations, int maxSize) { Set<String> fingerprints = new HashSet<>(); List<List<CourseIntelligentPageResponse>> result = new ArrayList<>(); for (List<CourseIntelligentPageResponse> combination : allCombinations) { String fingerprint = generateCombinationFingerprint(combination); if (!fingerprints.contains(fingerprint)) { fingerprints.add(fingerprint); result.add(combination); if (result.size() >= maxSize) break; } } return result; } /** * 生成组合指纹 */ private String generateCombinationFingerprint(List<CourseIntelligentPageResponse> combination) { return combination.stream() .map(c -> String.valueOf(c.getId())) .sorted() .collect(Collectors.joining(",")); } /** * 备用方法:快速生成近似组合(当精确组合不足时) */ public List<List<CourseIntelligentPageResponse>> generateApproximateCombinations( int targetHours, int minCourses, int maxCourses, List<CourseIntelligentPageResponse> courses, int numCombinations, int tolerance) { List<CourseIntelligentPageResponse> validCourses = courses.stream() .filter(c -> c.getHourCount() > 0) .sorted((c1, c2) -> Integer.compare(c2.getHourCount(), c1.getHourCount())) .limit(MAX_TOTAL_COURSES) .collect(Collectors.toList()); List<List<CourseIntelligentPageResponse>> results = new ArrayList<>(); Set<String> fingerprints = new HashSet<>(); // 尝试目标学时附近的组合 for (int offset = 0; offset <= tolerance && results.size() < numCombinations; offset++) { for (int hours = targetHours - offset; hours <= targetHours + offset; hours++) { if (hours <= 0) continue; List<List<CourseIntelligentPageResponse>> combinations = findCombinationsBacktrackOptimized(validCourses, hours, minCourses, maxCourses, numCombinations - results.size()); for (List<CourseIntelligentPageResponse> comb : combinations) { String fingerprint = generateCombinationFingerprint(comb); if (!fingerprints.contains(fingerprint)) { fingerprints.add(fingerprint); results.add(comb); if (results.size() >= numCombinations) break; } } if (results.size() >= numCombinations) break; } } return results; } }优化,使用内存小,cup小
最新发布
10-11
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值