当前位置: 首页 > news >正文

Json字符串内容比较-超实用版

背景

之前有类似接口diff对比,数据对比的测试需求,涉及到json格式的数据对比,调研了几个大神们分享的代码,选了一个最符合自己需求的研究了下。

说明

这个对比方法,支持JsonObject和JsonArray类型的数据对比,支持:

  • 深度的对比:list变化(个数、内容)、层级结构变化

  • 字段的对比:新增、修改、删除数据可察觉,能找到对应的旧数据

  • 支持特定字段忽略对比

输出的对比结果格式为:

源码分为JsonCompareUtils, JsonAndMapSortUtils两个类,对比入口是compareTwoJson方法

核心逻辑在JsonCompareUtils类中,JsonAndMapSortUtils主要做过程中的数据排序功能,相对独立。

 上源码:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Stream;public class JsonCompareUtils {//标志位:对json报文中含有JsonArray类型的数据是否进行排序private static boolean isSort;private Map<String, Object> oldJsonToMap = new LinkedHashMap<>();private Map<String, Object> newJsonToMap = new LinkedHashMap<>();//每一个实体里的排序字段private static Map<String, String> filedNameMap = new HashMap<>();static {filedNameMap.put("ojb1", "id");filedNameMap.put("ojb2", "id");}//可以跳过比对的字段private static String[] skipCompareFiledNameMap = {"createTime"};/*** 两json报文比对入口** @param oldJsonStr* @param newJsonStr* @return*/public String compare2Json(String oldJsonStr, String newJsonStr) {/*** 递归遍历json对象所有的key-value,以map形式的path:value进行存储* 然后对两个map进行比较*/convertJsonToMap(JSON.parseObject(oldJsonStr), "", false);convertJsonToMap(JSON.parseObject(newJsonStr), "", true);//获取比较结果Map<String, Object> differenceMap = compareTwoMaps(oldJsonToMap, newJsonToMap);String diffJsonResult = convertMapToJson(differenceMap);return diffJsonResult;}/*** 将json数据转换为map存储--用于后续比较map** @param json* @param root* @param isNew 区别新旧报文*/private void convertJsonToMap(Object json, String root, boolean isNew) {if (json instanceof JSONObject) {JSONObject jsonObject = ((JSONObject) json);Iterator iterator = jsonObject.keySet().iterator();while (iterator.hasNext()) {Object key = iterator.next();Object value = jsonObject.get(key);String newRoot = "".equals(root) ? key + "" : root + "." + key;fillInResultMap(value, newRoot, isNew);}} else if (json instanceof JSONArray) {JSONArray jsonArray = (JSONArray) json;//将jsonArray进行排序if (isSort) {//需要排序String sortEntityName = root.substring(root.lastIndexOf(".") + 1);//需要排序 获取排序字段String sortFiledName = filedNameMap.get(sortEntityName);if (!StringUtils.isEmpty(sortFiledName)) {jsonArray = JsonAndMapSortUtils.jsonArrayToSort(jsonArray, sortFiledName, true);}}final JSONArray jsonArray1 = jsonArray;Stream.iterate(0, integer -> integer + 1).limit(jsonArray1.size()).forEach(index -> {Object value = jsonArray1.get(index);String newRoot = "".equals(root) ? "[" + index + "]" : root + ".[" + index + "]";fillInResultMap(value, newRoot, isNew);});}}/*** 封装json转map后的数据** @param value* @param newRoot* @param isNew   区别新旧json*/public void fillInResultMap(Object value, String newRoot, boolean isNew) {if (value instanceof JSONObject || value instanceof JSONArray) {convertJsonToMap(value, newRoot, isNew);} else {//设置跳过比对的字段,直接不装入mapboolean check = ArrayUtils.contains(JsonCompareUtils.skipCompareFiledNameMap, newRoot);if (!check){if (!isNew) {oldJsonToMap.put(newRoot, value);} else {newJsonToMap.put(newRoot, value);}}}}/*** 比较两个map,将不同的数据以map形式存储并返回** @param oldJsonMap* @param newJsonMap* @return*/private Map<String, Object> compareTwoMaps(Map<String, Object> oldJsonMap, Map<String, Object> newJsonMap) {//1.将newJsonMap的不同数据装进oldJsonMap,同时删除oldJsonMap中与newJsonMap相同的数据newJsonMap.forEach((k, v) -> {Map<String, Object> differenceMap = new HashMap<>();if (oldJsonMap.containsKey(k)) {Object oldValue = oldJsonMap.get(k);if (v.equals(oldValue)) {oldJsonMap.remove(k);} else {differenceMap.put("oldValue", oldValue);differenceMap.put("newValue", v);oldJsonMap.put(k, differenceMap);}} else {differenceMap.put("oldValue", "no exists " + k);differenceMap.put("newValue", v);oldJsonMap.put(k, differenceMap);}});//2.统一oldJsonMap中newMap不存在的数据的数据结构,便于解析oldJsonMap.forEach((k, v) -> {if (!(v instanceof Map)) {Map<String, Object> differenceMap = new HashMap<>();differenceMap.put("oldValue", v);differenceMap.put("newValue", "no exists " + k);oldJsonMap.put(k, differenceMap);}});return oldJsonMap;}/*** 将已经找出不同数据的map根据key的层级结构封装成json返回** @param map* @return*/private String convertMapToJson(Map<String, Object> map) {JSONObject resultJSONObject = new JSONObject();for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {Map.Entry<String, Object> item = it.next();String key = item.getKey();Object value = item.getValue();String[] paths = key.split("\\.");int i = 0;//用於深度標識對象Object remarkObject = null;int indexAll = paths.length - 1;while (i <= paths.length - 1) {String path = paths[i];if (i == 0) {//初始化对象标识if (resultJSONObject.containsKey(path)) {remarkObject = resultJSONObject.get(path);} else {if (indexAll > i) {if (paths[i + 1].matches("\\[[0-9]+\\]")) {remarkObject = new JSONArray();} else {remarkObject = new JSONObject();}resultJSONObject.put(path, remarkObject);} else {resultJSONObject.put(path, value);}}i++;continue;}//匹配集合对象if (path.matches("\\[[0-9]+\\]")) {int startIndex = path.lastIndexOf("[");int endIndext = path.lastIndexOf("]");int index = Integer.parseInt(path.substring(startIndex + 1, endIndext));if (indexAll > i) {if (paths[i + 1].matches("\\[[0-9]+\\]")) {while (((JSONArray) remarkObject).size() <= index) {if (((JSONArray) remarkObject).size() == index) {((JSONArray) remarkObject).add(index, new JSONArray());} else {((JSONArray) remarkObject).add(null);}}} else {while (((JSONArray) remarkObject).size() <= index) {if (((JSONArray) remarkObject).size() == index) {((JSONArray) remarkObject).add(index, new JSONObject());} else {((JSONArray) remarkObject).add(null);}}}remarkObject = ((JSONArray) remarkObject).get(index);} else {while (((JSONArray) remarkObject).size() <= index) {if (((JSONArray) remarkObject).size() == index) {((JSONArray) remarkObject).add(index, value);} else {((JSONArray) remarkObject).add(null);}}}} else {if (indexAll > i) {if (paths[i + 1].matches("\\[[0-9]+\\]")) {if (!((JSONObject) remarkObject).containsKey(path)) {((JSONObject) remarkObject).put(path, new JSONArray());}} else {if (!((JSONObject) remarkObject).containsKey(path)) {((JSONObject) remarkObject).put(path, new JSONObject());}}remarkObject = ((JSONObject) remarkObject).get(path);} else {((JSONObject) remarkObject).put(path, value);}}i++;}}return JSON.toJSONString(resultJSONObject);}public boolean isSort() {return isSort;}public void setSort(boolean sort) {isSort = sort;}public static void main(String[] args) {String oldStr = "{\"abilityLevel\":\"2020101240000000000002\",\"activityId\":\"202208301413310000412\",\"addLibTime\":1662083360000,\"ansKnowModelIds\":\"1#201812051814150000475\",\"answer\":\"AB\",\"ascriptionItemLib\":\"0\",\"attributeList\":[{\"content\":\"<p>A</p>\",\"id\":\"202209020949170005783\",\"itemId\":\"202209020949150001521\",\"knowModelRelId\":\"201812051814150000475\",\"name\":\"A\",\"sort\":1,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">B</p>\",\"id\":\"202209020949170005784\",\"itemId\":\"202209020949150001521\",\"name\":\"B\",\"sort\":2,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">C</p>\",\"id\":\"202209020949170005785\",\"itemId\":\"202209020949150001521\",\"name\":\"C\",\"sort\":3,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">D</p>\",\"id\":\"202209020949170005786\",\"itemId\":\"202209020949150001521\",\"name\":\"D\",\"sort\":4,\"type\":\"option\"},{\"content\":\"11\",\"createTime\":1662083368000,\"createTimeString\":\"2022-09-02 09:49:28\",\"creater\":\"10001\",\"id\":\"202209020949170005787\",\"itemId\":\"202209020949150001521\",\"name\":\"大纲依据\",\"searchFlag\":\"1\",\"sort\":1,\"subItemTypeAttrId\":\"100041\",\"type\":\"expandAttr\"},{\"content\":\"11\",\"createTime\":1662083370000,\"createTimeString\":\"2022-09-02 09:49:30\",\"creater\":\"10001\",\"id\":\"202209020949280005788\",\"itemId\":\"202209020949150001521\",\"name\":\"教材依据\",\"searchFlag\":\"1\",\"sort\":2,\"subItemTypeAttrId\":\"100042\",\"type\":\"expandAttr\"},{\"content\":\"11\",\"createTime\":1662083371000,\"createTimeString\":\"2022-09-02 09:49:31\",\"creater\":\"10001\",\"id\":\"202209020949290005789\",\"itemId\":\"202209020949150001521\",\"name\":\"关键字\",\"searchFlag\":\"1\",\"sort\":3,\"subItemTypeAttrId\":\"100043\",\"type\":\"expandAttr\"}],\"auditCount\":0,\"auditStatus\":0,\"childItemList\":[],\"createTime\":1662083350000,\"createTimeString\":\"2022-09-02 09:49:10\",\"creater\":\"10001\",\"delFlag\":\"0\",\"difficult\":\"3\",\"id\":\"202209020949150001521\",\"isComposite\":0,\"isTopVersion\":0,\"itemCode\":\"KJCJ202209020949140001501\",\"itemContent\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">2.<span style=\\\"color: #333333; font-family: Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 14px; text-align: justify; background-color: #FFFFFF;\\\">按照并购双方行业相关性划分,判断并购类型(横向并购or混合并购)</span></p>\",\"itemKnowledgeList\":[{\"id\":\"202209020949300001537\",\"itemId\":\"202209020949150001521\",\"knowledgeId\":\"1240004\",\"knowledgeStr\":\"2020年经济法基础/第一章总论/第一节法律基础/一、法和法律/(一)法和法律的概念\",\"level\":\"1\",\"pid\":\"202209020946580001519\"}],\"itemLevel\":1,\"itemSource\":\"202208301413310000412\",\"itemTypeId\":\"4\",\"itemVersion\":\"1\",\"keyWord\":\"\",\"knowledgeId\":\"1240004\",\"knowledgeStr\":\"2020年经济法基础/第一章总论/第一节法律基础/一、法和法律/(一)法和法律的概念\",\"knowledgeSyllabusName\":\"2020年经济法基础\",\"lockStatus\":1,\"modifyChlidItems\":[],\"paperCount\":0,\"paperItemRelation\":{},\"paperStructure\":{},\"parentId\":\"202209020946580001519\",\"processedItemContent\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">2.<span style=\\\"color: #333333; font-family: Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 14px; text-align: justify; background-color: #FFFFFF;\\\">按照并购双方行业相关性划分,判断并购类型(横向并购or混合并购)</span></p>\",\"score\":2,\"sort\":2,\"sourceType\":\"2\",\"structId\":\"\",\"subItemTypeId\":\"20180228155501000004\",\"subjectId\":\"4\",\"updateTime\":1662083350000,\"updateTimeString\":\"2022-09-02 09:49:10\",\"updater\":\"10001\"}";String newStr = "{\"abilityLevel\":\"2020101240000000000002\",\"activityId\":\"202208301413310000412\",\"addLibTime\":1662083360000,\"analysis\":\"\",\"ansKnowModelIds\":\"1#201812051814150000475\",\"answer\":\"AB\",\"ascriptionItemLib\":\"0\",\"attributeList\":[{\"content\":\"<p>A</p>\",\"id\":\"202209021135210005855\",\"itemId\":\"202209020949150001521\",\"knowModelRelId\":\"201812051814150000475\",\"name\":\"A\",\"sort\":1,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">B</p>\",\"id\":\"202209021135210005856\",\"itemId\":\"202209020949150001521\",\"name\":\"B\",\"sort\":2,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">C</p>\",\"id\":\"202209021135210005857\",\"itemId\":\"202209020949150001521\",\"name\":\"C\",\"sort\":3,\"type\":\"option\"},{\"content\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">D</p>\",\"id\":\"202209021135210005858\",\"itemId\":\"202209020949150001521\",\"name\":\"D\",\"sort\":4,\"type\":\"option\"},{\"content\":\"11\",\"createTime\":1662089721000,\"createTimeString\":\"2022-09-02 11:35:21\",\"creater\":\"10001\",\"id\":\"202209021135210005859\",\"itemId\":\"202209020949150001521\",\"name\":\"大纲依据\",\"searchFlag\":\"1\",\"sort\":1,\"subItemTypeAttrId\":\"100041\",\"type\":\"expandAttr\"},{\"content\":\"11\",\"createTime\":1662089721000,\"createTimeString\":\"2022-09-02 11:35:21\",\"creater\":\"10001\",\"id\":\"202209021135210005860\",\"itemId\":\"202209020949150001521\",\"name\":\"教材依据\",\"searchFlag\":\"1\",\"sort\":2,\"subItemTypeAttrId\":\"100042\",\"type\":\"expandAttr\"},{\"content\":\"11\",\"createTime\":1662089722000,\"createTimeString\":\"2022-09-02 11:35:22\",\"creater\":\"10001\",\"id\":\"202209021135210005861\",\"itemId\":\"202209020949150001521\",\"name\":\"关键字\",\"searchFlag\":\"1\",\"sort\":3,\"subItemTypeAttrId\":\"100043\",\"type\":\"expandAttr\"}],\"auditCount\":0,\"auditStatus\":0,\"childItemList\":[],\"createTime\":1662083350000,\"createTimeString\":\"2022-09-02 09:49:10\",\"creater\":\"10001\",\"delFlag\":\"0\",\"difficult\":\"5\",\"id\":\"202209020949150001521\",\"isComposite\":0,\"isTopVersion\":0,\"itemCode\":\"KJCJ202209020949140001501\",\"itemContent\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">2.<span style=\\\"color: #333333; font-family: Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 14px; text-align: justify; background-color: #FFFFFF;\\\">按照并购双方行业相关性划分,判断并购类型(横向并购or混合并购)</span></p>\",\"itemKnowledgeList\":[{\"id\":\"202209021135230001557\",\"itemId\":\"202209020949150001521\",\"knowledgeId\":\"1240004\",\"knowledgeStr\":\"2020年经济法基础/第一章总论/第一节法律基础/一、法和法律/(一)法和法律的概念\",\"level\":\"1\",\"pid\":\"202209020946580001519\"}],\"itemLevel\":1,\"itemSource\":\"202208301413310000412\",\"itemTypeId\":\"4\",\"itemVersion\":\"2\",\"keyWord\":\"\",\"knowledgeId\":\"1240004\",\"knowledgeStr\":\"2020年经济法基础/第一章总论/第一节法律基础/一、法和法律/(一)法和法律的概念\",\"knowledgeSyllabusName\":\"2020年经济法基础\",\"lockStatus\":1,\"modifyChlidItems\":[],\"paperCount\":0,\"paperItemRelation\":{},\"paperStructure\":{},\"parentId\":\"202209020946580001519\",\"processedItemContent\":\"<p style=\\\"font-family:&#39;Times New Roman&#39;,&#39;宋体&#39;;font-size:12pt;padding:0;margin:0;\\\">2.<span style=\\\"color: #333333; font-family: Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 14px; text-align: justify; background-color: #FFFFFF;\\\">按照并购双方行业相关性划分,判断并购类型(横向并购or混合并购)</span></p>\",\"score\":2,\"sort\":2,\"sourceType\":\"2\",\"structId\":\"\",\"subItemTypeId\":\"20180228155501000004\",\"subjectId\":\"4\",\"updateTime\":1662089720000,\"updateTimeString\":\"2022-09-02 11:35:20\",\"updater\":\"10001\"}";System.out.println(new JsonCompareUtils().compare2Json(oldStr, newStr));System.out.println("\n========测试复杂json的比对============");}
}

JsonAndMapSortUtils 用于jsonArray排序
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import sun.misc.ASCIICaseInsensitiveComparator;import java.util.*;public class JsonAndMapSortUtils {/*** map排序* @param map* @param keySort* @param <k>* @param <v>* @return*/public static <k,v> List mapByKeyToSort(Map<k,v> map , final Comparator keySort){List<Map.Entry<k,v>> entryList = new ArrayList<>(map.entrySet());Collections.sort(entryList, (o1, o2) -> keySort.compare(o1.getKey(),o2.getKey()));System.out.println("排序=====");entryList.forEach(m->{System.out.println(m.getKey()+"===>"+m.getValue());});return entryList;}/*** JSONArray排序* @param jsonArray* @param fildName* @param isAsc* @return*/public static JSONArray jsonArrayToSort(JSONArray jsonArray,final String fildName,final boolean isAsc){JSONArray afterSortJsonArray = new JSONArray();List<JSONObject> objectList = new ArrayList<>();jsonArray.forEach(obj ->{objectList.add((JSONObject)obj);});Collections.sort(objectList, (o1, o2) -> {String fildValueA = o1.getString(fildName);String fildValueB = o2.getString(fildName);if (isAsc){return fildValueA.compareTo(fildValueB);}return fildValueB.compareTo(fildValueA);});objectList.forEach(obj->{afterSortJsonArray.add(obj);});return afterSortJsonArray;}/***准备map测试数据*/public static Map<String,String> getMapData(){LinkedHashMap<String,String> map = new LinkedHashMap<>();map.put("key1","测试1");map.put("key3","测试3");map.put("key5","测试5");map.put("key2","测试2");map.put("key4","测试4");return map;}/***准备json测试数据*/public static JSONArray getJsonArrayData(){JSONArray jsonArray = new JSONArray();JSONObject jsonObject1 = new JSONObject();jsonObject1.put("userId","1001");jsonObject1.put("name","测试1");jsonArray.add(jsonObject1);JSONObject jsonObject3 = new JSONObject();jsonObject3.put("userId","1003");jsonObject3.put("name","测试3");jsonArray.add(jsonObject3);JSONObject jsonObject2 = new JSONObject();jsonObject2.put("userId","1002");jsonObject2.put("name","测试2");jsonArray.add(jsonObject2);return jsonArray;}public static void main(String[] args) {Map<String,String> map = JsonAndMapSortUtils.getMapData();JSONArray jsonArray = JsonAndMapSortUtils.getJsonArrayData();List afterSortMap = JsonAndMapSortUtils.mapByKeyToSort(map,new ASCIICaseInsensitiveComparator());JSONArray afterSortJsonArray_isAsc = JsonAndMapSortUtils.jsonArrayToSort(jsonArray,"userId",true);JSONArray afterSortJsonArray_noAsc = JsonAndMapSortUtils.jsonArrayToSort(jsonArray,"userId",false);System.out.println("map排序前:"+map);System.out.println("map排序后:"+afterSortMap+"\n");System.out.println("JsonArray排序前:"+jsonArray);System.out.println("JsonArray排序后==》升序:"+afterSortJsonArray_isAsc);System.out.println("JsonArray排序后==》降序:"+afterSortJsonArray_noAsc);}}


源码走读
整个源码调用链路如下图,简单来说过程就是:object拆分解析-新旧数据逐个对比-结果信息组装三个步骤

相关文章:

Json字符串内容比较-超实用版

背景 之前有类似接口diff对比&#xff0c;数据对比的测试需求&#xff0c;涉及到json格式的数据对比&#xff0c;调研了几个大神们分享的代码&#xff0c;选了一个最符合自己需求的研究了下。 说明 这个对比方法&#xff0c;支持JsonObject和JsonArray类型的数据对比&#x…...

Redis系列之客户端Redisson

概述 官方推荐的客户端&#xff0c;支持Redis单实例、Redis哨兵、Redis Cluster、Redis master-slave等各种部署架构。 GitHub&#xff0c; 功能&#xff1a; 分布式锁 分布式锁 使用Redisson提供的分布式锁的一个最常见场景&#xff0c;应用部署为多个节点&#xff0c;然…...

centos 端口被占用的快速排查方式

问题笔记 centos 端口被占用的快速排查方式 centos 端口被占用的快速排查方式 这里说一个我刚刚遇到的问题&#xff0c;解决步骤用来记录&#xff0c;方便以后自己查询。 nginx配置完index.html测试文件&#xff0c;发现一直显示的404页面。 我跑到服务器上想重启一下nginx …...

Java“牵手”淘宝商品列表数据,关键词搜索淘宝商品数据接口,淘宝API申请指南

淘宝商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问淘宝商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…...

OpenEuler/CentOS如何修改密码策略

密码策略文件&#xff1a; /etc/pam.d/system-auth 找到行&#xff1a; password requisite pam_pwquality.so try_first_pass local_users_only 为保证安全&#xff0c;可以将这一行注释掉&#xff0c;添加一行&#xff0c;最后结果如下&#xff1a; #password …...

# Spring MVC与RESTful API:如何设计高效的Web接口

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

Scrum敏捷模式的优势点、实践经验及适用企业

Scrum敏捷模式是一种灵活、适应性强的开发方法&#xff0c;其核心理念是以短周期、高频率的方式进行项目开发&#xff0c;确保团队能够快速响应变化。 Scrum包含三个角色&#xff1a;产品负责人&#xff08;Product Owner&#xff09;、Scrum Master和开发团队&#xff08;Tea…...

【C++杂货铺】探索stack和queue的底层实现

文章目录 一、stack的介绍和使用1.1 stack的介绍1.2 stack的使用1.2.1 最小栈1.2.2 栈的压入、弹出序列1.2.3 逆波兰表达式求值1.2.4 用栈实现队列 二、queue的介绍和使用2.1 queue的介绍2.2 queue的使用2.2.1 二叉树的层序遍历 三、模拟实现3.1 stack模拟实现3.2 queue模拟实现…...

“系统的UI”——SystemUI

SystemUI的实现 以StatusBar为例&#xff0c;来分析下Android系统具体是如何实现它们的。 相关代码分为两部分&#xff0c;即&#xff1a; Service部分 代码路径&#xff1a;frameworks/base/services/java/com/android/server。 应用部分 代码路径&#xff1a;frameworks…...

类和对象:构造函数,析构函数与拷贝构造函数

1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器…...

谈谈Java的特点和优点以及选择Java的原因

&#xfeff;​ 如果面试官问你&#xff1a;请你说说Java的特点和优点&#xff0c;为什么要选择Java&#xff1f;你该怎么回答&#xff1f; 得分点 Java的特点 Java与C的区别 Java的优点标准回答 Java是一门非常纯粹的面向对象的编程语言&#xff0c;它吸收了C语言的各种优…...

消息队列(MQ)面试

目录 讲一讲MQ 面试官: 在你之前的项目中&#xff0c;你是否使用过消息队列&#xff08;MQ&#xff09;&#xff1f;能详细介绍一下你在项目中如何使用MQ吗&#xff1f; 在用户和用户之间的多对多聊天通信中如何使用&#xff0c;请具体来讲一下。 那你可以讲一下消息的确认…...

无涯教程-JavaScript - COUPNUM函数

描述 COUPNUM函数返回结算日和到期日之间应付的息票数量,四舍五入到最接近的整数。 语法 COUPNUM (settlement, maturity, frequency, [basis])争论 Argument描述Required/OptionalSettlement 证券的结算日期。 证券结算日期是指在发行日期之后将证券交易给买方的日期。 Re…...

上海控安携汽车网络安全新研产品出席AUTOSEMO“恒以致远,共创共赢”主题研讨会

8月31日&#xff0c;AUTOSEMO“恒以致远&#xff0c;共创共赢”主题研讨会在天津成功召开。本次大会由中国汽车工业协会软件分会中国汽车基础软件生态标委会&#xff08;简称&#xff1a;AUTOSEMO&#xff09;与天津市西青区人民政府联合主办。现场汇聚了100余位来自产学研政企…...

小程序引入高德/百度地图坐标系详解

小程序引入高德/百度地图坐标系详解 官网最近更新时间&#xff1a;最后更新时间: 2021年08月17日 高德官网之在原生小程序中使用的常见问题 链接 目前在小程序中使用 高德地图只支持以下功能 &#xff1a;地址描述、POI和实时天气数据 小结&#xff1a;从高德api中获取数…...

英诺森 “供应链智能数据平台”荣获“科技进步奖”

近日&#xff0c;2023年中国物流与采购联合会科学技术奖正式公布&#xff0c;该奖项经国家科技部批准&#xff0c;在国家科学技术奖励工作办公室登记备案&#xff0c;是我国物流行业最具影响力的奖项之一。 英诺森联合客户申报的科技项目“英诺森供应链智能数据平台”&#xf…...

kafka 3.5 主题分区的Follower创建Fetcher线程从Leader拉取数据源码

Kakfa集群有主题&#xff0c;每一个主题下又有很多分区&#xff0c;为了保证防止丢失数据&#xff0c;在分区下分Leader副本和Follower副本&#xff0c;而kafka的某个分区的Leader和Follower数据如何同步呢&#xff1f;下面就是讲解的这个 首先要知道&#xff0c;Follower的数据…...

Golang web 项目中实现自定义 recovery 中间件

为什么需要实现自定义 recovery 中间件&#xff1f; 在 Golang 的 Web 项目中&#xff0c;自定义 recovery 中间件是一种常见的做法&#xff0c;用于捕获并处理应用程序的运行时错误&#xff0c;以避免整个应用程序崩溃并返回对应格式的响应数据。 很多三方 web 框架&#xf…...

Direct3D绘制旋转立方体例程

初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp #include <windows.h> #include "d3dUtility.h" #include <d3dx9math.h>IDirect3DDevice9* Device NULL; IDirect3DVertexBuffer9* VB NULL; IDirect3…...

ElementUI浅尝辄止31:Tabs 标签页

选项卡组件&#xff1a;分隔内容上有关联但属于不同类别的数据集合。 常见于网站内容信息分类或app内容信息tab分类 1.如何使用&#xff1f; Tabs 组件提供了选项卡功能&#xff0c;默认选中第一个标签页&#xff0c;你也可以通过 value 属性来指定当前选中的标签页。 <temp…...

将 ChatGPT 用于数据科学项目的指南

推荐&#xff1a;使用 NSDT场景编辑器 快速搭建3D应用场景 我们都知道 ChatGPT 的受欢迎程度以及人们如何使用它来提高生产力。但是&#xff0c;如果您是新手&#xff0c;则值得注册ChatGPT免费演示并尝试它所能做的一切。您还应该参加我们的 ChatGPT 简介课程&#xff0c;学习…...

06-JVM对象内存回收机制深度剖析

上一篇&#xff1a;05-JVM内存分配机制深度剖析 堆中几乎放着所有的对象实例&#xff0c;对堆垃圾回收前的第一步就是要判断哪些对象已经死亡&#xff08;即不能再被任何途径使用的对象&#xff09;。 1.引用计数法 给对象中添加一个引用计数器&#xff0c;每当有一个地方引…...

[VSCode] 替换掉/去掉空行

VSCode中使用快捷键CtrlH&#xff0c;出现替换功能&#xff0c;在上面的“查找”框中输入正则表达式&#xff1a; ^\s*(?\r?$)\n然后选择右侧的“使用正则表达式”&#xff1b;“替换”框内为空&#xff0c;点击右侧的“全部替换”&#xff0c;即可去除所有空行。 参考 [VS…...

时序分解 | MATLAB实现ICEEMDAN+SE改进的自适应经验模态分解+样本熵重构分量

时序分解 | MATLAB实现ICEEMDANSE改进的自适应经验模态分解样本熵重构分量 目录 时序分解 | MATLAB实现ICEEMDANSE改进的自适应经验模态分解样本熵重构分量效果一览基本介绍程序设计参考资料 效果一览 基本介绍 ICEEMDANSE改进的自适应经验模态分解样本熵重构分量 包括频谱图 避…...

python内网环境安装第三方包【内网搭建开发环境】

文章目录 一、问题二、解决方法三、代码实现一、问题 内网安装第三方包的应用场景,一般是一些需要在没网的环境下进行开发的情况。这些环境一般仅支持本地局域网访问,所以只能在不下载任何第三方包的情况下艰难开发。 二、解决方法 将当前应用依赖的第三方包提前下载到本地…...

7.13 在SpringBoot中 正确使用Validation实现参数效验

文章目录 前言引入Maven依赖一、POST/PUT RequestBody参数校验1.1 Valid或Validated注解配合constraints注解1.2 测试运行 二、GET/DELETE RequestParam参数校验2.1 Validated注解配合constraints注解2.2 测试运行 三、GET 无注解参数校验3.1 Valid或Validated注解配合constrai…...

Matlab图像处理之Lee滤波器

目录 一、前言:二、LEE滤波器2.1 LEE滤波器原理2.2 LEE滤波器实现步骤三、MATLAB代码示例一、前言: LEE滤波器是一种常用于合成孔径雷达(SAR)图像去噪的滤波器。它能增强图像的局部对比度。今天我们将通过MATLAB来实现这种滤波器。 二、LEE滤波器 2.1 LEE滤波器原理 LEE滤…...

C++系列-const修饰的常函数

const修饰的常函数 常函数常对象 常函数 成员函数后加const&#xff0c;称为常函数。常函数内部不可以修改成员变量。常函数内可以改变加了mutable修饰的成员变量。 code:#include <iostream>using namespace std;class Horse{public:int age 3;mutable string color …...

fail-safe 机制与 fail-fast 机制

Fail-fast 表示快速失败&#xff0c;在集合遍历过程中&#xff0c;一旦发现容器中的数据被修改了&#xff0c;会立刻抛出 ConcurrentModificationException 异常&#xff0c;从而导致遍历失败&#xff0c;像这种情况 定义一个 Map 集合&#xff0c;使用 Iterator 迭代器进行数据…...

LLM 位置编码及外推

RoPE https://zhuanlan.zhihu.com/p/629681325 PI 位置插值&#xff08;POSITION INTERPOLATION&#xff09;显著改善RoPE的外推能力。你只需要对PT&#xff08;pretraining)模型fine-turing最多1000步就能实现。PI是通过将线性的缩小了输入位置的索引使其匹配原始上下文窗口…...

铁岭网站建设/seo01网站

TextView加载字体包在 Android 中&#xff0c;若需要使得某个TextView加载字体包&#xff0c;使用以下方式即可&#xff1a;Typeface typeFace Typeface.createFromAsset(getAssets(),"fonts/Bold.otf");textView.setTypeface(typeFace);至于字体包的位置&#xff1a…...

宁德市路桥建设有限公司网站/手机优化助手下载

问题所在 当我用pycharm打印pandas代码结果的时候&#xff0c;发现它总是被折叠起来&#xff0c;被三个点所代替 解决办法 在打印结果前面加上下面两行代码即可&#xff0c;也就是说&#xff0c;我们需要将行和列的最大值限制给去掉即可。 pd.set_option(display.max_column…...

wordpress 添加文章/推广app拿返佣的平台

说起沟通科技&#xff0c;也许一般人会觉得很陌生&#xff0c;毕竟这家成立于2000年的高新企业&#xff0c;前几年一直比较沉寂&#xff0c;在默默无闻地做着前期的铺垫工作&#xff0c;但对于应用软件和远程接入这些相关的行业而言&#xff0c;从2005年开始&#xff0c;沟通科…...

网络建设公司的问答营销案例/旺道seo推广有用吗

免责声明&#xff1a;文章内容仅为个人技术思考&#xff0c;不作任何形式的技术推荐或商业推广。网络爬虫作为当下热门的技术手段之一&#xff0c;被越来越多的数据型用户视为重要的信息获取方法。本文将从预备知识、技术原理两方面以个人视角介绍该技术途径。1.重识网页1.1 HT…...

驻马店做网站哪家好/如何检测网站是否安全

https://jingyan.baidu.com/article/cd4c2979bf38bb356f6e6006.html 以上是原文链接 摘要&#xff1a; 首先&#xff0c;在桌面点击鼠标右键&#xff0c;点击“新建”&#xff0c;新建一个Excel表格&#xff0c;如图所示&#xff1b; 在表格里输入内容&#xff0c;发现内容…...

网站制作 公开课/广州营销型网站

序列是Python中最基本的数据结构。序列中的每个元素都分配一个数字 - 它的位置&#xff0c;或索引&#xff0c;第一个索引是0&#xff0c;第二个索引是1&#xff0c;依此类推。Python有6个序列的内置类型&#xff0c;但最常见的是列表和元组。序列都可以进行的操作包括索引&…...