springboot集成websocket实现实时大量数据,效率性能高
前言
小编我将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注一下!
也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远!让我们在成长的道路上互相学习,让我们共同进步,欢迎关注!
针对websocket技术的金融alltick股票实战经验,通过调用第三方wss的的数据,来获取实时数据,并保持性能高及效率高
1、在springboot中引入websocket相应的jar包
<!-- Spring Boot WebSocket Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
2.创建webSocketConfig 暴露endpoint端点
package com.nq.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;@Configuration
public class WebSocketConfig {@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}
3:创建websocket客户端用于连接第三方的wss
package com.nq.common;import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nq.pojo.Stock;
import com.nq.service.IStockService;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.StringUtils;
import com.nq.utils.redis.RedisShardedPool;
import com.nq.utils.redis.RedisShardedPoolUtils;
import com.nq.vo.stock.StockListVO;
import com.nq.vo.websocket.CodeVo;
import com.nq.vo.websocket.StockVo;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hpsf.Decimal;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.websocket.*;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URI;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;/*** @Description: websocket客户端* 一共2800条code产品数据,每个webSocketServer处理1000条数据,分三个webSocketServer处理* 提高效率* @Author: jade* @Date: 2021/8/25 10:25*/
@ClientEndpoint
@Slf4j
@Component //交给spring容器管理
@Data
public class WebSocketJavaExample {private Session session; //会话对象private Boolean flag = true; //用来拯救流的关闭标识符private Map<String,StockVo> stockVoMap;private List<StockVo> stockList; //返回给客户端的封装数据List集合public final static Integer MAXCAP = 1000; //一次性以1000条@Resource //使用@Resource来装配,不然会为nullIStockService stockService;private ObjectMapper objectMapper=new ObjectMapper();@OnOpenpublic void onOpen(Session session) {this.session = session;}
/**
接收第三方服务端的消息
**/@OnMessagepublic void onMessage(String message) {if(message.indexOf("data") != -1) {try {JSONObject jsonObject = JSONUtil.parseObj(message);String dataStr = jsonObject.getStr("data");//第三方响应的Json数据if (dataStr != null) {
// JSONArray jsonArray = JSONUtil.parseArray(dataStr);
// JSONObject jsonObject = JSONUtil.parseObj(dataStr);
// jsonArray.stream().forEach(item -> {JSONObject json = JSONUtil.parseObj(dataStr);Optional<StockVo> stockVo = stockList.stream()//Optional为java8的Stream API中使用,处理可能为null的元素.filter(p -> json.getStr("code").equals(p.getCode().concat(".US"))).findFirst();
// .filter(p -> json.getStr("code").equals(p.getCode())).findFirst();stockVo.ifPresent(vo -> {// 当前价格BigDecimal nowPrice = new BigDecimal(json.getStr("price"));BigDecimal preClosePrice = vo.getPreclose_px();vo.setType(json.getStr("trade_direction"));// alltick websocket 获取数据 替换原来的当前价格和涨幅vo.setNowPrice(nowPrice);// 计算涨幅BigDecimal chg = nowPrice.subtract(preClosePrice).divide(preClosePrice, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));vo.setHcrate(chg);});log.info("Optional<StockVo> send message to client"+stockVo);
// });} else {log.error("data字段不是一个有效的JSON数组: {}", dataStr);}} catch (Exception e) {log.error("解析消息时发生异常: {}", e.getMessage());}}}@OnClosepublic void onClose(Session session, CloseReason closeReason) {flag=false;log.info("AllTick API Docs流已关闭,关闭原因:{}",closeReason.toString());}@OnErrorpublic void onError(Throwable e) {log.error("AllTick API Docs连接异常{}",e.getMessage());}@Asyncpublic void sendMessage(String key,String message) throws Exception {session.getBasicRemote().sendText(message);
// log.info("client:{}, AllTick API Docs 请求报文: {}", key, message);
// if (this.session != null && this.session.isOpen()) {
// this.session.getBasicRemote().sendText(message);
// } else {
// log.error("会话已关闭,无法发送消息: {}", key);
// }}//websocket地址private String url=PropertiesUtil.getProperty("WebSocket.url");//token数据private String token= PropertiesUtil.getProperty("WebSocket.token");public static List<WebSocketJavaExampleInfo> webSocketJavaExampleList = new ArrayList<>();@PostConstructpublic void initPool() {new Thread(()->{ //另外起一个线程执行websocket,不影响主线程run();}).start();}@PreDestroypublic void destroy() {if (this.session != null && this.session.isOpen()) {try {this.session.close();} catch (IOException e) {log.error("关闭WebSocket连接时发生异常: {}", e.getMessage());}}}@Asyncpublic void run(){try {List<Stock> list = stockService.findStockList();int len = list.size();int capacity = (int) Math.ceil((double) len / MAXCAP);//向上取整
// int capacity = (int) Math.ceil(len / MAXCAP);
// if (capacity<1 || len % capacity != 0 ) {
// capacity++;
// }List<CodeVo> codeVos = new ArrayList<>();log.info("开始连接AllTick API Docs,请求url:{}",url.concat(token));WebSocketContainer container = ContainerProvider.getWebSocketContainer();URI uri = new URI(url.concat(token)); // Replace with your websocket endpoint URLfor (int i = 0; i < capacity; i++) {WebSocketJavaExample client = new WebSocketJavaExample(); //多个客户client执行,每个客户端执行1000条数据container.connectToServer(client, uri);List<Stock> list1 = list.stream().skip(i * MAXCAP).limit(MAXCAP).collect(Collectors.toList());stockList = new ArrayList<>();list1.forEach(item -> {CodeVo codeVo = new CodeVo();codeVo.setCode(item.getStockCode().concat(".US"));
// codeVo.setCode(item.getStockCode());codeVos.add(codeVo);StockVo stockVo = new StockVo();try {// 数据初始化String us = RedisShardedPoolUtils.get(item.getStockGid(), 4);StockListVO stockListVO = objectMapper.readValue(us, StockListVO.class);stockVo.setName(stockListVO.getName());stockVo.setCode(stockListVO.getCode());stockVo.setGid(stockListVO.getGid());stockVo.setStock_type(stockListVO.getStock_type());stockVo.setType(stockListVO.getType());stockVo.setHcrate(stockListVO.getHcrate());stockVo.setOpen_px(new BigDecimal(stockListVO.getOpen_px()));stockVo.setNowPrice(new BigDecimal(stockListVO.getNowPrice()));stockVo.setPreclose_px(new BigDecimal(stockListVO.getPreclose_px()));stockVo.setIsOption(Integer.valueOf(stockListVO.getIsOption()));stockList.add(stockVo);} catch (JsonProcessingException e) {log.info("redis数据转换对象stockListVO异常",e.getMessage());}});JSONArray symbolList = new JSONArray(codeVos); // 直接将List转换为JSONArrayclient.setStockList(stockList);// 使用LinkedHashMap来保持顺序Map<String, Object> messageMap = new LinkedHashMap<>();messageMap.put("cmd_id", 22004);messageMap.put("seq_id", 123);messageMap.put("trace", "3baaa938-f92c-4a74-a228-fd49d5e2f8bc-1678419657806");Map<String, Object> dataMap = new LinkedHashMap<>();dataMap.put("symbol_list", symbolList);messageMap.put("data", dataMap);// 将LinkedHashMap转换为JSONObjectJSONObject message2 = new JSONObject(messageMap);String message = message2.toString();
// String message = "{\"cmd_id\":22004,\"seq_id\":123,\"trace\":\"3baaa938-f92c-4a74-a228-fd49d5e2f8bc-1678419657806\",\"data\":{\"symbol_list\": "+ JSONUtil.toJsonStr(codeVos) +"}}";client.sendMessage("client" + i, message);webSocketJavaExampleList.add(new WebSocketJavaExampleInfo(client, "client" + i,message));codeVos.clear();// 创建一个TimerTask任务int finalI = i;TimerTask task3 = new TimerTask() {@SneakyThrows@Overridepublic void run() {//定时获取心跳try {client.sendMessage("client" + finalI,"{\n" +" \"cmd_id\":22000,\n" +" \"seq_id\":123,\n" +" \"trace\":\"3baaa938-f92c-4a74-a228-fd49d5e2f8bc-1678419657806\",\n" +" \"data\":{\n" +" }\n" +"}");} catch (Exception e) {log.error(e.getMessage());}}};new Timer().schedule(task3, 10000,10000);new Thread().sleep(2000);}}catch (Exception e){e.printStackTrace();log.error("AllTick API Docs 连接失败:{}",e.getMessage());}}
/**
定时任务,应用启动后延迟 2.5 分钟开始执行,之后每隔 2.5 分钟执行一次,去勘测是否流关闭,然后拯救连接websocket
**/@Scheduled(fixedRate = 1 * 15 * 10000,initialDelay = 150000)public void Daemon() throws Exception {WebSocketContainer container = ContainerProvider.getWebSocketContainer();URI uri = new URI(url.concat(token)); // Replace with your websocket endpoint URLfor(WebSocketJavaExampleInfo webSocketJavaExampleInfo:webSocketJavaExampleList){if(!webSocketJavaExampleInfo.getClient().flag){container.connectToServer(webSocketJavaExampleInfo.getClient(), uri);webSocketJavaExampleInfo.getClient().sendMessage(webSocketJavaExampleInfo.getKey(), webSocketJavaExampleInfo.getMessage());}}}
}@Data
class WebSocketJavaExampleInfo{private WebSocketJavaExample client;private String key;private String message;public WebSocketJavaExampleInfo(WebSocketJavaExample client, String key,String message) {this.client = client;this.key = key;this.message = message;}
}
4、创建websocket服务端用于连接客户端,及供前端访问
package com.nq.common;import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.nq.vo.websocket.StockVo;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.config.annotation.EnableWebSocket;import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;import static com.nq.common.WebSocketJavaExample.MAXCAP;
import static com.nq.common.WebSocketJavaExample.webSocketJavaExampleList;@ServerEndpoint("/ws/{userId}")
@EnableWebSocket
@Component
@Data
public class WebSocketServer {private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);private static final Integer pageSize = 100;//页码private Integer pageNo;//页数/*** concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();/*** 与某个客户端的连接会话,需要通过它来给客户端发送数据*/private Session session;/*** 接收userId*/private String userId = "";/*** 查询code*/private String code = "";/*** 连接建立成功调用的方法*/@OnOpenpublic void onOpen(Session session, @PathParam("userId") String userId) {this.session = session;this.userId = userId;if (webSocketMap.containsKey(userId)) {webSocketMap.remove(userId);webSocketMap.put(userId, this);} else {webSocketMap.put(userId, this);}}/*** 连接关闭调用的方法*/@OnClosepublic void onClose() {if (webSocketMap.containsKey(userId)) {webSocketMap.remove(userId);}}/*** 收到客户端消息后调用的方法** @param message 客户端发送过来的消息*/@OnMessagepublic void onMessage(String message, Session session) {log.info("用户消息:" + userId + ",报文:" + message);JSONObject jsonObject = JSONUtil.parseObj(message);
// pageSize = jsonObject.getInt("pageSize");pageNo = jsonObject.getInt("pageNo");code = jsonObject.getStr("code");
// if (ObjectUtil.isNotEmpty(code)) { //如果code不为空,则查询并推送数据
// queryAndSendStockVo(code, session);
// }}/*** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());}/*** 实现服务器主动推送*/public void sendMessage(String message) throws IOException {this.session.getBasicRemote().sendText(message);}/*** 群发消息** @throws IOException*/@PostConstructpublic void BroadCastInfo() throws IOException, InterruptedException {log.info("开始轮询批量推送数据");ThreadUtil.execAsync(() -> {run();});}public void run() {WebSocketServer webSocketServer;List<StockVo> list = null;List<StockVo> additionalList = null;List<StockVo> list2 = null;while (true) {try {if (webSocketMap.size() > 0) {for (Map.Entry<String, WebSocketServer> stringWebSocketServerEntry : webSocketMap.entrySet()) {webSocketServer = stringWebSocketServerEntry.getValue();if (ObjectUtil.isEmpty(webSocketServer.pageNo) && ObjectUtil.isNotEmpty(webSocketServer.pageSize) && ObjectUtil.isEmpty(webSocketServer.getCode())) {//如果默认没有参数 就传输3千条
// if(ObjectUtil.isEmpty(webSocketServer.pageNo)) {//如果默认没有参数 就传输3千条list = webSocketJavaExampleList.get(0).getClient().getStockList().stream().limit(1000).collect(Collectors.toList());} else if (ObjectUtil.isNotEmpty(webSocketServer.pageNo)) {int pageSize = webSocketServer.pageSize;int pageNo = webSocketServer.pageNo;Integer size = pageNo * pageSize;
// int capacity = (int) Math.ceil(size / 20);int capacity = (int) Math.ceil(size / MAXCAP);int pageno = (capacity * 1000 / pageSize);pageNo -= pageno;if (capacity == 0) {list = webSocketJavaExampleList.get(capacity).getClient().getStockList().stream().skip(0).limit(pageNo * pageSize).collect(Collectors.toList());}if (capacity == 1) {list = webSocketJavaExampleList.get(0).getClient().getStockList().stream().collect(Collectors.toList());additionalList = webSocketJavaExampleList.get(capacity).getClient().getStockList().stream().skip(0).limit(size - (MAXCAP * capacity)).collect(Collectors.toList());list = Stream.concat(list.stream(), additionalList.stream()).collect(Collectors.toList());}if (capacity == 2) {list = webSocketJavaExampleList.get(0).getClient().getStockList().stream().collect(Collectors.toList());list2 = webSocketJavaExampleList.get(1).getClient().getStockList().stream().collect(Collectors.toList());additionalList = webSocketJavaExampleList.get(capacity).getClient().getStockList().stream().skip(0).limit(size - (MAXCAP * capacity)).collect(Collectors.toList());list = Stream.concat(Stream.concat(list.stream(), list2.stream()), additionalList.stream()).collect(Collectors.toList());}
// list = webSocketJavaExampleList.get(capacity).getClient().getStockList().stream().skip((pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList());} else {String queryCode = webSocketServer.getCode();// 使用并行流处理数据,减少嵌套循环list = webSocketJavaExampleList.parallelStream().flatMap(webSocketJavaExampleInfo -> webSocketJavaExampleInfo.getClient().getStockList().stream()).filter(stockVo -> stockVo.getCode().contains(queryCode)).collect(Collectors.toList());}try {stringWebSocketServerEntry.getValue().sendMessage(JSONUtil.toJsonStr(list));} catch (IOException e) {log.error("用户编码为:{},推送ws数据异常,异常原因:{}", webSocketServer.getUserId(), e.getMessage());}}}} catch (Exception e) {log.error("推送失败: {}", e.getMessage());} finally {try {new Thread().sleep(2000);} catch (InterruptedException e) {log.error("没有客户端:{},webSocketMap:{}", e.getMessage(), webSocketMap.size());}}}}}
以上是基于小编在开发过程中,针对websocket技术的实战经验,通过调用第三方wss的的数据,来获取实时数据
相关文章:
springboot集成websocket实现实时大量数据,效率性能高
前言 小编我将用CSDN记录软件开发求学之路上亲身所得与所学的心得与知识,有兴趣的小伙伴可以关注一下! 也许一个人独行,可以走的很快,但是一群人结伴而行,才能走的更远!让我们在成长的道路上互相学习&…...
游戏引擎学习第80天
Blackboard:增强碰撞循环,循环遍历两种类型的 t 值 计划对现有的碰撞检测循环进行修改,以便实现一些新的功能。具体来说,是希望处理在游戏中定义可行走区域和地面的一些实体。尽管这是一个2D游戏,目标是构建一些更丰富…...
Windows 上的 MySQL 8.4.3 和 WSL(Ubuntu)的 MySQL 8.0.40 之间配置 主从同步
在 Windows 上的 MySQL 8.4.3 和 WSL(Ubuntu)的 MySQL 8.0.40 之间配置 主从同步(Master-Slave Replication) 的过程略有不同,因为两者的 MySQL 版本和环境存在差异。以下是详细步骤,帮助你完成跨平台的主从…...
【狂热算法篇】探秘图论之 Floyd 算法:解锁最短路径的神秘密码(通俗易懂版)
: 羑悻的小杀马特.-CSDN博客羑悻的小杀马特.擅长C/C题海汇总,AI学习,c的不归之路,等方面的知识,羑悻的小杀马特.关注算法,c,c语言,青少年编程领域.https://blog.csdn.net/2401_82648291?spm1010.2135.3001.5343 在本篇文章中,博主将带大家去学习所谓的…...
Sentinel配置流控规则详解
前言 在微服务架构中,流量控制(Flow Control)是保障服务稳定性的重要手段之一。Sentinel作为一款开源的流量控制、熔断降级Java库,以其丰富的应用场景和完善的监控能力,在微服务保护中扮演了重要角色。本文将详细介绍…...
解锁动态规划的奥秘:从零到精通的创新思维解析(6)
解锁动态规划的奥秘:从零到精通的创新思维解析(6) 前言: 在动态规划的众多问题中,多状态DP问题是一个非常重要的类别。它的难点在于如何设计合适的状态表示和转移方程,从而高效地解决问题。 多状态DP的核…...
Qwen2.5 3B、7B、14B在文本按照规范进行标准化改写任务上的表现
任务介绍:军事杂志方向资料标准化改写任务 1. 任务目标 本任务的目标是对军事杂志领域的非标准化资料进行改写,确保其符合军事文献的写作规范和标准格式。通过改写,保留原文的核心内容和信息,同时提升语言的准确性、简洁性和专业…...
Oracle报错ORA-01078、LRM-00109
虚拟机异常关机后,rac数据库备机无法启动数据库,报错如下 解决方法: 找到如下路径文件 执行: cp init.ora.016202516818 /u01/app/oracle/product/19.3.0/db/dbs/ mv init.ora.016202516818 initplm2.ora 再次进入命令行sqlpl…...
免费为企业IT规划WSUS:Windows Server 更新服务 (WSUS) 之快速入门教程(一)
哈喽大家好,欢迎来到虚拟化时代君(XNHCYL),收不到通知请将我点击星标!“ 大家好,我是虚拟化时代君,一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…...
Titans 架构中的记忆整合:Memory as a Context;Gated Memory;Memory as a Layer
Titans 架构中的记忆整合 Titans 架构中的记忆整合 Memory as a Context(MAC)变体:在处理长序列数据时,将序列分段,对于当前段 S ( t ) S^{(t)}...
无缝过渡:将 Ansys 子结构模型转换为 Nastran
了解如何将 Ansys 子结构模型无缝转换为 Nastran,以满足有效载荷动态模型要求 Ansys 子结构模型的优势 Ansys 子结构模型为从事大型装配体结构分析和仿真的工程师和分析师提供了多项优势。 这些模型通过将复杂结构划分为更小、更易于管理的子结构,可以…...
小哆啦的跳跃挑战:能否突破迷宫的极限?
小哆啦开始力扣每日一题的第六天 https://leetcode.cn/problems/jump-game/description/ 小哆啦的跳跃挑战:能否突破迷宫的极限? 第一阶段:小哆啦的初次尝试 —— 盲目跳跃 小哆啦刚进入跳跃之城,他决定采用一种非常直接的方法来…...
KubeSphere部署安装,接入KubeKey安装的k8s集群
KubeSphere安装接入KubeKey安装的k8s集群 文章目录 KubeSphere安装接入KubeKey安装的k8s集群 一.NFS安装配置1.服务器安装NFS服务2.下载并部署 NFS Subdir External Provisioner1).下载部署文件2).创建 NameSpace3).创建 RBAC 资源4).配置 deployment.yaml5).部署 Storage Clas…...
Object常用的方法及开发中的使用场景
在前端开发中,Object 对象提供了许多常用的方法,这些方法帮助我们操作对象的属性和结构。以下是常用的 Object 方法及其功能简要说明: 对象常用的方法 1. 创建对象 Object.create(proto[, propertiesObject]) 创建一个具有指定原型对象和属性…...
SQL2000在win10上安装的方法
安装前最好先关闭防火墙和一些杀毒软件,因为这些软件在安装过程中可能会碰到注册表等一下杀毒软件比较敏感的地带,如果违反杀毒软件的规则会被当做病毒强行终止删除 首相找到C盘下window文件中的sysWOW64文件 鼠标右键,点击属性、安全、高级 …...
Windows图形界面(GUI)-QT-C/C++ - QT 对话窗口
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 模态对话框 非模态对话框 文件对话框 基本概念 静态函数 常见属性 颜色对话框 基本概念 静态函数 常见属性 字体对话框 基本概念 静态函数 常见属性 输入对话框 基本概念 …...
Java语言的数据结构
Java语言中的数据结构 引言 在计算机科学中,数据结构是指一种特定的方式来组织和存储数据,以便能够高效地进行访问和修改。Java作为一种广泛使用的编程语言,其内置的数据结构和集合框架为程序员提供了便利的工具来管理数据。本文将深入探讨…...
【12】Word:张老师学术论文❗
目录 题目 NO2 NO3 NO4 NO5 NO6 NO7.8 题目 NO2 布局→页面设置→纸张:A4→页边距:上下左右边距→文档网格:只指定行网格→版式:页眉和页脚:页脚距边界:1.4cm居中设置论文页码:插入…...
大疆最新款无人机发布,可照亮百米之外目标
近日,DJI 大疆发布全新小型智能多光旗舰 DJI Matrice 4 系列,包含 Matrice 4T 和 Matrice 4E 两款机型。DJI Matrice 4E 价格为27888 元起,DJI Matrice 4T价格为38888元起。 图片来源:大疆官网 DJI Matrice 4E DJI Matrice 4T D…...
《小迪安全》学习笔记05
目录 读取: 写入: (其中的读取和写入时我认为比较重要的,所以单独做成了目录,这里的读取和写入是指在进行sql注入的时候与本地文件进行的交互) 好久没发博客了。。。从这篇开始的小迪安全学习笔记就开始…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
