Java实现协同过滤推荐系统:Spring Boot与Redis实战
1. 项目概述智能推荐系统的核心价值推荐系统早已渗透进我们数字生活的方方面面。打开电商App看到的猜你喜欢刷短视频时平台推送的内容甚至外卖软件里你可能想吃的栏目背后都是推荐算法在发挥作用。作为推荐系统中最经典、应用最广泛的算法之一协同过滤(Collaborative Filtering)以其直观的原理和稳定的效果成为开发者入行推荐系统的首选技术路径。这次我们要用Java技术栈实现一个完整的协同过滤推荐系统。选择Java主要基于三点考虑首先Java在企业级应用开发中占据主导地位特别适合构建需要高并发的推荐服务其次Spring Boot框架能大幅降低系统复杂度最后结合Redis可以轻松解决推荐系统最棘手的高性能缓存需求。这个方案在中小型推荐场景中完全能够支撑百万级用户量的实时推荐请求。2. 协同过滤算法深度解析2.1 协同过滤的两种实现路径协同过滤算法主要分为两大类基于用户的协同过滤(UserCF)和基于物品的协同过滤(ItemCF)。UserCF的核心思想是相似用户喜欢相似物品通过计算用户之间的相似度来推荐物品。比如用户A和用户B历史行为高度相似那么用户A喜欢的物品很可能也适合用户B。ItemCF则是喜欢相似物品的用户也喜欢该物品比如购买了手机的用户经常同时购买钢化膜系统就会给购买手机的用户推荐钢化膜。在Java实现中我们选择ItemCF作为基础算法原因有三一是ItemCF更适合物品数量相对稳定的场景二是物品相似度矩阵比用户相似度矩阵更稳定不需要频繁更新三是ItemCF的推荐结果更容易解释适合电商等需要展示推荐理由的场景。2.2 相似度计算的数学原理相似度计算是协同过滤的核心常用的有余弦相似度和皮尔逊相关系数。我们采用改进的余弦相似度公式sim(i,j) Σ(u∈U)(R(u,i)-R̄(i))(R(u,j)-R̄(j)) / [√Σ(u∈U)(R(u,i)-R̄(i))² * √Σ(u∈U)(R(u,j)-R̄(j))²]其中R(u,i)表示用户u对物品i的评分R̄(i)是物品i的平均分。这个公式在Java中实现时需要注意使用BigDecimal处理浮点运算避免精度丢失对没有共同评分的物品对要特殊处理引入惩罚因子降低热门物品的相似度权重2.3 推荐生成的工程实现得到物品相似度矩阵后推荐生成分为三步获取目标用户的交互物品列表为每个交互物品找出最相似的K个物品按加权相似度排序生成推荐列表在Java中这个过程可以优化为public ListRecommendedItem recommend(long userId, int howMany) { // 获取用户历史行为 ListItemInteraction interactions userDao.getInteractions(userId); // 计算候选物品得分 MapLong, Double candidateScores new HashMap(); for (ItemInteraction interaction : interactions) { ListSimilarItem similars similarityDao.getTopSimilarItems( interaction.getItemId(), 20); for (SimilarItem similar : similars) { double weightedScore interaction.getScore() * similar.getSimilarity(); candidateScores.merge(similar.getItemId(), weightedScore, Double::sum); } } // 过滤已交互物品并排序 return candidateScores.entrySet().stream() .filter(e - !interactions.contains(e.getKey())) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .limit(howMany) .map(e - new RecommendedItem(e.getKey(), e.getValue())) .collect(Collectors.toList()); }3. Spring Boot工程搭建3.1 项目结构设计我们采用典型的三层架构src/ ├── main/ │ ├── java/ │ │ ├── com.example.recommend/ │ │ │ ├── config/ # 配置类 │ │ │ ├── controller/ # 接口层 │ │ │ ├── service/ # 业务逻辑 │ │ │ ├── dao/ # 数据访问 │ │ │ ├── entity/ # 数据实体 │ │ │ └── RecommendApplication.java │ └── resources/ │ ├── application.yml │ └── redis/ ├── test/ # 测试代码关键依赖选择dependencies !-- Spring Boot基础 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 数据访问 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId /dependency !-- 工具类 -- dependency groupIdorg.apache.commons/groupId artifactIdcommons-collections4/artifactId version4.4/version /dependency dependency groupIdcom.google.guava/groupId artifactIdguava/artifactId version31.1-jre/version /dependency /dependencies3.2 Redis缓存设计推荐系统面临的最大挑战是性能问题。用户相似度计算的时间复杂度是O(n²)当用户量达到百万级时实时计算完全不现实。我们的解决方案是使用Redis缓存三个关键数据结构用户行为记录Hash结构keyuser:${userId}, fielditemId, valuescore物品相似度矩阵ZSET结构keyitem:sim:${itemId}, membersimilarItemId, scoresimilarity推荐结果缓存String结构keyrec:${userId}, valueJSON格式的推荐列表缓存更新策略用户行为变更时实时更新用户行为Hash物品相似度矩阵每天凌晨全量更新推荐结果设置30分钟过期时间Java配置示例Configuration public class RedisConfig { Bean public RedisTemplateString, Object redisTemplate( RedisConnectionFactory factory) { RedisTemplateString, Object template new RedisTemplate(); template.setConnectionFactory(factory); // 使用Jackson序列化 Jackson2JsonRedisSerializerObject serializer new Jackson2JsonRedisSerializer(Object.class); ObjectMapper mapper new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.activateDefaultTyping( mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(serializer); template.setHashKeySerializer(new StringRedisSerializer()); template.setHashValueSerializer(serializer); return template; } }4. 核心功能实现细节4.1 数据预处理模块真实场景的用户行为数据往往存在以下问题数据稀疏大多数用户只与少量物品有交互数据倾斜热门物品被大量交互数据噪声存在刷单等异常行为我们的预处理流程包括public class DataPreprocessor { // 降噪过滤异常用户 public ListUserBehavior removeNoise(ListUserBehavior behaviors) { // 统计用户活跃度 MapLong, Integer userActivity behaviors.stream() .collect(Collectors.groupingBy( UserBehavior::getUserId, Collectors.summingInt(b - 1))); // 使用Tukeys fences方法识别异常值 double[] activities userActivity.values().stream() .mapToDouble(v - v).sorted().toArray(); double q1 activities[activities.length / 4]; double q3 activities[activities.length * 3 / 4]; double iqr q3 - q1; double lowerBound q1 - 1.5 * iqr; double upperBound q3 1.5 * iqr; return behaviors.stream() .filter(b - { int activity userActivity.get(b.getUserId()); return activity lowerBound activity upperBound; }) .collect(Collectors.toList()); } // 热门物品降权 public ListUserBehavior reweightByPopularity(ListUserBehavior behaviors) { MapLong, Integer itemPopularity behaviors.stream() .collect(Collectors.groupingBy( UserBehavior::getItemId, Collectors.summingInt(b - 1))); double avgPopularity itemPopularity.values().stream() .mapToInt(v - v).average().orElse(1.0); return behaviors.stream() .map(b - { double popularity itemPopularity.get(b.getItemId()); double weight Math.sqrt(avgPopularity / popularity); return new UserBehavior( b.getUserId(), b.getItemId(), b.getScore() * weight); }) .collect(Collectors.toList()); } }4.2 相似度计算优化直接计算所有物品对的相似度时间复杂度是O(n²)我们采用以下优化策略基于MapReduce的分布式计算public class SimilarityCalculator { Autowired private RedisTemplateString, Object redisTemplate; public void calculateAllSimilarities(ListUserBehavior behaviors) { // 阶段1建立物品-用户倒排索引 MapLong, ListLong itemUsersMap behaviors.stream() .collect(Collectors.groupingBy( UserBehavior::getItemId, Collectors.mapping(UserBehavior::getUserId, Collectors.toList()))); // 阶段2并行计算物品相似度 ListLong itemIds new ArrayList(itemUsersMap.keySet()); ExecutorService executor Executors.newFixedThreadPool(8); for (int i 0; i itemIds.size(); i) { Long item1 itemIds.get(i); executor.submit(() - { for (int j i 1; j itemIds.size(); j) { Long item2 itemIds.get(j); double sim cosineSimilarity( itemUsersMap.get(item1), itemUsersMap.get(item2)); if (sim 0) { redisTemplate.opsForZSet().add( item:sim: item1, item2, sim); redisTemplate.opsForZSet().add( item:sim: item2, item1, sim); } } }); } executor.shutdown(); try { executor.awaitTermination(1, TimeUnit.HOURS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } private double cosineSimilarity(ListLong users1, ListLong users2) { SetLong intersection new HashSet(users1); intersection.retainAll(users2); if (intersection.isEmpty()) return 0; double dotProduct intersection.size(); double norm1 Math.sqrt(users1.size()); double norm2 Math.sqrt(users2.size()); return dotProduct / (norm1 * norm2); } }相似度矩阵稀疏化只保留每个物品top100的相似物品大幅减少存储空间4.3 实时推荐接口推荐API需要考虑以下几个关键点响应时间控制在200ms以内结果多样性避免每次推荐相同物品冷启动问题新用户/新物品的推荐策略实现代码RestController RequestMapping(/recommend) public class RecommendController { Autowired private RecommendService recommendService; GetMapping(/forUser) public ResponseEntityListRecommendedItem recommendForUser( RequestParam long userId, RequestParam(defaultValue 10) int howMany, RequestParam(defaultValue 0.3) double diversity) { // 从缓存获取推荐结果 String cacheKey rec: userId; String cached redisTemplate.opsForValue().get(cacheKey); if (cached ! null) { ListRecommendedItem items parseCachedResult(cached); return ResponseEntity.ok(items); } // 实时计算 ListRecommendedItem items recommendService.recommend(userId, howMany * 2); // 多样性处理随机采样 Collections.shuffle(items); items items.subList(0, Math.min(howMany, items.size())); // 更新缓存 redisTemplate.opsForValue().set( cacheKey, serializeResult(items), 30, TimeUnit.MINUTES); return ResponseEntity.ok(items); } // 冷启动策略 GetMapping(/coldStart) public ResponseEntityListRecommendedItem coldStartRecommend( RequestParam(defaultValue 10) int howMany) { // 返回热门物品随机物品的混合 ListRecommendedItem popular recommendService.getPopularItems(howMany / 2); ListRecommendedItem random recommendService.getRandomItems(howMany / 2); ListRecommendedItem result new ArrayList(); result.addAll(popular); result.addAll(random); Collections.shuffle(result); return ResponseEntity.ok(result); } }5. 性能优化与生产实践5.1 性能压测数据我们使用JMeter对推荐接口进行压测单机部署(4核8G)的测试结果并发用户数平均响应时间吞吐量错误率5068ms720/s0%100112ms890/s0%200203ms980/s0.2%500467ms1050/s1.5%关键优化手段使用Caffeine实现JVM层缓存缓存热门物品的相似度数据对Redis批量执行pipeline操作采用异步非阻塞的WebFlux替代传统MVC5.2 常见问题排查推荐结果重复率高检查多样性参数是否生效验证相似度矩阵是否正常更新查看用户行为数据是否过于集中新物品得不到推荐实现基于内容的混合推荐策略在相似度计算中加入内容特征设置新物品的初始曝光权重Redis内存占用过高优化相似度矩阵存储结构使用HASH替代ZSET设置合理的过期时间对相似度数据进行压缩存储5.3 监控与告警配置生产环境必须完善的监控指标接口性能99线响应时间、错误率Redis健康度内存使用率、命中率、慢查询推荐效果点击率、转化率、多样性指标Spring Boot Actuator配置示例management: endpoints: web: exposure: include: health,metrics,prometheus metrics: export: prometheus: enabled: true tags: application: ${spring.application.name}6. 系统扩展与演进6.1 混合推荐策略纯协同过滤存在冷启动和多样性问题可以引入基于内容的推荐使用物品标签、分类等信息热门榜单保证基础推荐效果实时兴趣基于最近点击行为的短期兴趣6.2 深度学习整合传统协同过滤可以升级为神经协同过滤(NCF)使用Embedding表示用户和物品神经网络拟合交互函数离线训练在线服务的架构Java生态支持dependency groupIdorg.deeplearning4j/groupId artifactIddeeplearning4j-core/artifactId version1.0.0-beta7/version /dependency6.3 推荐效果评估体系建立完整的评估体系离线指标准确率、召回率、覆盖率在线指标CTR、转化率、停留时长业务指标GMV提升、用户留存率A/B测试框架设计public class ABTestFramework { public enum Strategy { CF, // 纯协同过滤 HYBRID, // 混合推荐 DNN // 深度学习 } public Strategy assignStrategy(long userId) { // 根据用户ID哈希分桶 int bucket (int)(userId % 100); if (bucket 70) return Strategy.CF; if (bucket 90) return Strategy.HYBRID; return Strategy.DNN; } public void trackConversion(long userId, long itemId) { Strategy strategy assignStrategy(userId); // 上报转化数据到分析系统 analyticsClient.trackEvent( userId, conversion, Map.of(strategy, strategy.name())); } }7. 项目部署与运维7.1 容器化部署Dockerfile配置示例FROM openjdk:11-jre WORKDIR /app COPY target/recommend-service.jar . EXPOSE 8080 ENTRYPOINT [java, -jar, recommend-service.jar]Kubernetes部署描述apiVersion: apps/v1 kind: Deployment metadata: name: recommend-service spec: replicas: 3 selector: matchLabels: app: recommend template: metadata: labels: app: recommend spec: containers: - name: recommend image: recommend-service:1.0.0 ports: - containerPort: 8080 resources: requests: memory: 2Gi cpu: 1000m limits: memory: 4Gi cpu: 2000m7.2 灰度发布策略推荐系统的变更需要谨慎我们的发布流程先在5%的流量上验证新算法监控核心指标响应时间、错误率、点击率逐步放大流量比例全量后持续监控48小时7.3 灾备方案确保推荐服务高可用Redis集群部署主从切换本地缓存降级策略限流熔断配置Bean public CustomizerReactiveResilience4JCircuitBreakerFactory defaultCustomizer() { return factory - factory.configureDefault(id - new Resilience4JConfigBuilder(id) .circuitBreakerConfig(CircuitBreakerConfig.custom() .failureRateThreshold(50) .waitDurationInOpenState(Duration.ofMillis(1000)) .permittedNumberOfCallsInHalfOpenState(10) .slidingWindowSize(100) .build()) .timeLimiterConfig(TimeLimiterConfig.custom() .timeoutDuration(Duration.ofMillis(500)) .build()) .build()); }8. 项目演进路线从简单协同过滤出发可以逐步构建完整的推荐体系初级阶段1-2周实现基础ItemCF算法完成Spring Boot基础框架单机Redis缓存中级阶段3-4周引入用户CF实现混合推荐增加AB测试框架搭建基础监控体系高级阶段5-8周整合深度学习模型构建特征工程管道实现实时推荐更新优化阶段持续进行推荐效果调优性能极致优化算法持续迭代在实际项目中我们团队从零开始构建的推荐系统经过3个月的迭代使电商平台的推荐点击率提升了2.3倍转化率提升1.8倍。关键经验是不要追求算法的复杂性而要在基础算法上持续优化特征工程和工程实现。

相关新闻

思源宋体TTF:免费商用的专业中文字体终极指南

思源宋体TTF:免费商用的专业中文字体终极指南

思源宋体TTF:免费商用的专业中文字体终极指南 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 还在为寻找一款既专业又免费的中文字体而烦恼吗?思源宋体TTF&…

2026/7/29 10:47:34阅读更多 →
三月七小助手:崩坏星穹铁道自动化工具终极指南

三月七小助手:崩坏星穹铁道自动化工具终极指南

三月七小助手:崩坏星穹铁道自动化工具终极指南 【免费下载链接】March7thAssistant 崩坏:星穹铁道全自动 三月七小助手 项目地址: https://gitcode.com/gh_mirrors/ma/March7thAssistant 三月七小助手(March7thAssistant)是…

2026/7/29 10:47:34阅读更多 →
LeetCode 212题解析:Trie树优化单词搜索II算法

LeetCode 212题解析:Trie树优化单词搜索II算法

1. 问题背景与核心挑战LeetCode 212题"单词搜索II"是一个经典的二维网格搜索问题,要求在一个字符矩阵中找到所有出现在给定词典中的单词。这个问题看似简单,但实际上面临几个关键挑战:首先,直接使用暴力搜索&#xff08…

2026/7/29 10:47:34阅读更多 →
GitHub使用(1):从GitHub建立项目分支并克隆到本地(命令行操作)

GitHub使用(1):从GitHub建立项目分支并克隆到本地(命令行操作)

目录一、概述二、从GitHub建立项目分支并克隆到本地2.1 GitHub创建分支2.2 本地克隆三、GitHub和本地仓库关联使用3.1 本地修改3.2 推送本地到远程3.3 更新远程到本地四、基本指令4.1 账号配置4.2 新建、删除分支4.3 查看远程仓库关联情况、当前仓库提交记录和修改情况4.4 放弃…

2026/7/29 17:03:33阅读更多 →
单片机毕设选题推荐:基于 STM32 的自动手动双模式环境调控装置设计 基于 STM32 的多传感器环境数据采集与控制系统设计(010801)

单片机毕设选题推荐:基于 STM32 的自动手动双模式环境调控装置设计 基于 STM32 的多传感器环境数据采集与控制系统设计(010801)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/29 17:03:33阅读更多 →
范式锁死与真理突围:基于贾子公理体系对全球西方 AI 学术范式内生绝症、修补式改良困局及独立真理评判系统的深度研究

范式锁死与真理突围:基于贾子公理体系对全球西方 AI 学术范式内生绝症、修补式改良困局及独立真理评判系统的深度研究

范式锁死与真理突围:基于贾子公理体系对全球西方 AI 学术范式内生绝症、修补式改良困局及独立真理评判系统的深度研究作者:贾子(Kucius Teng,鸽姆智库创始人)单位:鸽姆智库(GG3M Think Tank&…

2026/7/29 17:03:33阅读更多 →
单片机毕设选题推荐:基于嵌入式单片机的门窗震动防盗设备开发 基于 STM32 的 OLED 显示震动安防系统设计(010701)

单片机毕设选题推荐:基于嵌入式单片机的门窗震动防盗设备开发 基于 STM32 的 OLED 显示震动安防系统设计(010701)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/29 17:03:33阅读更多 →
DE-Transformer在单变量时序预测中的Matlab实现与优化

DE-Transformer在单变量时序预测中的Matlab实现与优化

1. 项目概述:DE-Transformer在单变量时序预测中的应用 最近在整理时间序列预测的代码库时,发现DE-Transformer这个结合了差分进化(DE)算法和Transformer架构的混合模型,在单变量预测任务中表现相当亮眼。不同于传统的RNN/LSTM方案&#xff0c…

2026/7/29 17:03:33阅读更多 →
google企业账号已经提交-----需要等3天

google企业账号已经提交-----需要等3天

他说:你可能需要等几天

2026/7/29 17:01:33阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“!

28. Agent 执行到一半想暂停?用 interrupt 给它设个“关卡“! 在构建复杂的 Agent 系统时,我们经常会遇到这样的场景:Agent 正在执行一个多步骤的任务,比如“下单购买商品”,但执行到一半时,我们…

2026/7/29 0:01:46阅读更多 →
自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

自律同行,突破无界!NANK南卡正式官宣曾舜晞成为品牌代言人

近日,国际专注开放式技术研发的声学品牌Nank南卡,正式官宣实力艺人曾舜晞担任品牌代言人。消息一经发出便轰动全网。为什么耳机品牌不选择流量明星、老牌歌手?而且是选择曾舜晞?让我们一起来探索一下!比起短期的流量&a…

2026/7/29 0:01:46阅读更多 →
【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

【RT-DETR多模态创新改进】CVPR 2025 | 独家特征融合创新改进篇 | 引入RLAB残差线性注意力模块,有效融合并强调多尺度特征,多种改进点,适合红外与可见光融合目标检测任务,有效涨点

一、本文介绍 🔥本文在RT-DETR多模态融合目标检测中引入RLAB残差线性注意力模块,可在不同模态特征交互阶段进行多次残差细化,使可见光、红外等特征在尺度、语义和空间位置上更好对齐;随后将细化特征与解码器输出拼接并生成Q、K、V,通过线性注意力自适应强化关键通道、目…

2026/7/29 0:01:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/28 20:22:24阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/29 4:31:51阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →