ID-MAPPING解绑实现(图计算)

直接上代码吧。

/*** 这是一个无向图数据结构,支持非联通。* 支持ID-Mapping解绑使用* @Author Ma Shuai* @Date 9/13/24 5:45 PM* @Version 1.0*/public class UnbindGraph {private static String SPLIT = ":";public UnbindGraph() {this.adjacentNodeMap = new HashMap<>();this.nodeMessageMap = new HashMap<>();}@Datapublic class NodeMessage {private String  idType;private String  idValue;// key是业务来源table_name(业务来源唯一对应一个表) value是表主键PK。 Long类型有需要时可换成beanprivate Map<String, List<Long>> tableAndPKList;public NodeMessage(String idType, String idValue,String tableName, Long pk){this.idType = idType;this.idValue = idValue;this.tableAndPKList = new HashMap<>();this.tableAndPKList.put(tableName,new ArrayList<Long>(){{add(pk);}});}private void setTableAndPKList(Map<String, Set<Long>> tableAndPKList) {}public void setTableAndPKList(String tableName, Long pk) {if(!this.tableAndPKList.containsKey(tableName)){this.tableAndPKList.put(tableName,new ArrayList<Long>(){{add(pk);}});}else {this.tableAndPKList.get(tableName).add(pk);}}}//节点关系 node String=>idtype:idvalueprivate Map<String, Set<String>> adjacentNodeMap;//节点信息 node message (方便拓展性维护性以及空间的节省 单独Map存节点信息)private Map<String, NodeMessage> nodeMessageMap;/*** 添加节点关系 A-B* @param A* @param B*/public void addEdge(GraphNodeParameter A,GraphNodeParameter B){// 都不符合规范不入图(所以图结果集不存在不符合规范的数据会导致有的centerid对应的数据没有得到处理,最后要按照老的centerid逻辑删除数据)if(!checkGraphNodeParameterIsTrue(A)&&!checkGraphNodeParameterIsTrue(B)){return;}setAdjacentNodeRelation(A,B);}/*** A-B 入图* @param A* @param B*/private void setAdjacentNodeRelation(GraphNodeParameter A,GraphNodeParameter B) {//当前节点的预处理pretreatmentNode(A,B);// AB都合规if(checkGraphNodeParameterIsTrue(A)&&checkGraphNodeParameterIsTrue(B)){String idTypeValueA = A.getIdType()+SPLIT+A.getIdValue();String idTypeValueB = B.getIdType()+SPLIT+B.getIdValue();//无向setAdjacentNode(idTypeValueA, idTypeValueB);setAdjacentNode(idTypeValueB, idTypeValueA);}}/*** 存储节点信息、整理临接表* @param nodeParameters*/private void pretreatmentNode(GraphNodeParameter... nodeParameters) {for (GraphNodeParameter N : nodeParameters) {if(!checkGraphNodeParameterIsTrue(N)){continue;}//节点信息String idType = N.getIdType();String idValue = N.getIdValue();String idTypeValue = idType+SPLIT+idValue;String tableName = N.getTableName();Long pk = N.getPK();// pretreatment adjacentNodeMapif(!this.adjacentNodeMap.containsKey(idTypeValue)){this.adjacentNodeMap.put(idTypeValue,new HashSet<>());}// add NodeMessageif(!this.nodeMessageMap.containsKey(idTypeValue)) {this.nodeMessageMap.put(idTypeValue,new NodeMessage(idType,idValue,tableName,pk));}else {this.nodeMessageMap.get(idTypeValue).setTableAndPKList(tableName,pk);}}}/*** 设置临接关系* @param idTypeValueA* @param idTypeValueB*/private void setAdjacentNode(String idTypeValueA, String idTypeValueB) {this.adjacentNodeMap.get(idTypeValueA).add(idTypeValueB);}/*** 校验节点数据* @param nodeParameter* @return*/private boolean checkGraphNodeParameterIsTrue(GraphNodeParameter nodeParameter){returnnodeParameter != null&&!StringUtils.isEmptyOrWhitespaceOnly(nodeParameter.getIdValue())&&!StringUtils.isEmptyOrWhitespaceOnly(nodeParameter.getIdType());}/*** 图遍历,默认使用DFS* @return List<List<NodeMessage>> 存储多个连通图数据,每个List<NodeMessage>是同一个连通图的数据*/public List<List<NodeMessage>> traversingGraph(){return traversingGraph(true);}/*** DFS or BFS 遍历图,true使用DFS,false使用BFS,NULL默认使用DFS* @param b* @return List<List<NodeMessage>> 存储多个连通图数据,每个List<NodeMessage>是同一个连通图的数据*/public List<List<NodeMessage>> traversingGraph(Boolean b){b = b==null?true:b;//此数据结构是个非联通图,所以遍历完后要存储多组联通图,每个map属于同一个graph。List<List<NodeMessage>> nGraph = new ArrayList<>();Set<String> visited = new HashSet<>();Set<String> nodes = this.adjacentNodeMap.keySet();if(b){for (String start : nodes) {if (!visited.contains(start)) {nGraph.add(dfs(start,visited));}}}else {for (String start : nodes) {if (!visited.contains(start)) {nGraph.add(bfs(start,visited));}}}return nGraph;}/*** 广度优先(BFS)* @param start* @return List<NodeMessage> 存储同一个连通图的数据*/public List<NodeMessage> bfs(String start) {Set<String> visited = new HashSet<>();return bfs(start, visited);}/*** 广度优先(BFS)* @param start* @param visited* @return List<NodeMessage> 存储同一个连通图的数据*/public List<NodeMessage> bfs(String start, Set<String> visited) {List<NodeMessage> nodeMessages = new ArrayList<>();Queue<String> queue = new LinkedList<>();queue.offer(start);visited.add(start);while (!queue.isEmpty()){String current = queue.poll();//存储层次遍历的数据nodeMessages.add(this.nodeMessageMap.get(current));for (String adjacent : adjacentNodeMap.get(current)) {if(!visited.contains(adjacent)){queue.offer(adjacent);visited.add(adjacent);}}}return nodeMessages;}/*** 深度优先搜索(DFS)* @param start* @return List<NodeMessage> 存储同一个连通图的数据*/public List<NodeMessage> dfs(String start) {Set<String> visited = new HashSet<>();return dfs(start, visited);}/*** 深度优先搜索(DFS)* @param start* @return List<NodeMessage> 存储同一个连通图的数据*/public List<NodeMessage> dfs(String start, Set<String> visited) {List<NodeMessage> nodeMessages = new ArrayList<>();dfs(start, visited, nodeMessages);return nodeMessages;}/*** 深度优先搜索(DFS)* @param start* @param visited* @param nodeMessages 存储同一个连通图的数据*/private void dfs(String start, Set<String> visited, List<NodeMessage> nodeMessages) {if(visited.contains(start)) return;visited.add(start);nodeMessages.add(this.nodeMessageMap.get(start));for (String neighbor : this.adjacentNodeMap.get(start)) {dfs(neighbor,visited,nodeMessages);}}}

图的入参单独做了一个bean(可根据自己业务需求自定义,同理上述图算法中的NodeMessage类也可以自定义需要存储的节点信息)

/*** @Author Ma Shuai* @Date 2021-09-03 19:48* @Version 1.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GraphNodeParameter {private String  idType;private String  idValue;private String  tableName;private Long    pK;
}

测试:(需要解绑的关系不入图,然后再遍历图得到的就是解绑后的结果)

  @Testpublic void test1() {//创建图对象UnbindGraph unbindGraph = new UnbindGraph();// 添加连通关系1unbindGraph.addEdge(new GraphNodeParameter("mobile","mobile222","c_center_account_for_uc",123L),new GraphNodeParameter("userId","userId333","c_center_account_for_uc",123L));unbindGraph.addEdge(new GraphNodeParameter("unionId","unionId444","c_center_account_for_user_union",343L),new GraphNodeParameter("userId","userId333","c_center_account_for_user_union",343L));// 添加连通关系2unbindGraph.addEdge(new GraphNodeParameter("wxId","wxId111","c_center_account_for_user_union",24543L),null);unbindGraph.addEdge(new GraphNodeParameter("unionId","","c_center_account_for_user_union",24543L),new GraphNodeParameter("wxId","wxId111","c_center_account_for_user_union",24543L));// 添加连通关系3unbindGraph.addEdge(new GraphNodeParameter("mobile","mobile111","c_center_account_for_uc",24524L),new GraphNodeParameter("userId","userId111","c_center_account_for_uc",24524L));unbindGraph.addEdge(new GraphNodeParameter("unionId","unionId111","c_center_account_for_uc",35634L),new GraphNodeParameter("userId","userId111","c_center_account_for_uc",35634L));unbindGraph.addEdge(new GraphNodeParameter("unionId","unionId111","c_center_account_for_crm",2356345L),new GraphNodeParameter("customerId","customerId111","c_center_account_for_crm",2356345L));//图遍历List<List<UnbindGraph.NodeMessage>> lists = unbindGraph.traversingGraph();for (List<UnbindGraph.NodeMessage> list : lists) {System.out.println(list);}}

打印结果:

解释:idType和idValue相同时算作同一个节点,只不过添加相同节点时可能携带的信息不同。(比如相同的两个节点之间多条线,可以携带线的信息)

[UnbindGraph.NodeMessage(idType=wxId, idValue=wxId111, tableAndPKList={c_center_account_for_user_union=[24543, 24543]})]
[UnbindGraph.NodeMessage(idType=mobile, idValue=6a5af3a1467d36ed640aa7103e372e9c, tableAndPKList={c_center_account_for_uc=[24524]}), UnbindGraph.NodeMessage(idType=userId, idValue=userId111, tableAndPKList={c_center_account_for_uc=[24524, 35634]}), UnbindGraph.NodeMessage(idType=unionId, idValue=unionId111, tableAndPKList={c_center_account_for_uc=[35634], c_center_account_for_crm=[2356345]}), UnbindGraph.NodeMessage(idType=customerId, idValue=customerId111, tableAndPKList={c_center_account_for_crm=[2356345]})]
[UnbindGraph.NodeMessage(idType=unionId, idValue=unionId444, tableAndPKList={c_center_account_for_user_union=[343]}), UnbindGraph.NodeMessage(idType=userId, idValue=userId333, tableAndPKList={c_center_account_for_uc=[123], c_center_account_for_user_union=[343]}), UnbindGraph.NodeMessage(idType=mobile, idValue=557cd727e8f4d02ad2c295aa1d436e82, tableAndPKList={c_center_account_for_uc=[123]})]

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/145789.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(五)-聚合

聚合 聚合基于Query结果的统计&#xff0c;执行过程是搜索的一部分&#xff0c;Onesearch支持0代码构建聚合&#xff0c;聚合目前完全在引擎层 0代码聚合 上图是聚合的配置&#xff0c;包括2个pdm文档聚合统计 termsOfExt term桶聚合&#xff0c;统计ext&#xff0c;如&…

热点|创邻图查询范式引爆LDBC TUC2024

2024年8月30日至31日&#xff0c;创邻科技Galaxybase团队联合蚂蚁集团TuGraph团队、阿里巴巴GraphScope团队共同主办第18届LDBC TUC会议。在本次会议中&#xff0c;来自全球图数据库领域的学者和技术专家做了很多精彩的分享&#xff0c;共同探讨图技术的最新进展。创邻科技Gala…

MySQL高阶1853-转换日期格式

目录 题目 准备数据 分析数据 总结 题目 给定一个Days表&#xff0c;请你编写SQL查询语句&#xff0c;将Days表中的每一个日期转化为"day_name, month_name day, year"格式的字符串。 返回的结果表 不计顺序 。 准备数据 Create table If Not Exists Days (d…

【Kubernetes知识点】HPA如何控制不同的资源实现自动扩缩容?

【Kubernetes知识点】HPA如何控制不同的资源实现自动扩缩容&#xff1f; 目录 1 概念 1.1 什么是HPA1.2 Deployment 与 HPA 的关系 1.2.1 工作原理 1.3 StatefulSet 与 HPA 的关系 1.3.1 工作原理 2 实验案例&#xff1a;HPA 控制 StatefulSet 进行扩缩容 2.1 部署一个有状态…

[产品管理-28]:NPDP新产品开发 - 26 - 产品生命周期管理 - 产品上市的八大步骤

目录 一、产品发布 1.1 传统的产品上市发布步骤&#xff1a;线性一次性发布 1. 产品概念提出与市场调研 2. 产品开发与测试 3. 生产准备与质量控制 4. 营销策略制定 5. 产品上市发布 6. 持续优化与迭代 1.2 新型的产品上市发布步骤&#xff1a;逐步迭代&#xff0c;多…

【mysql技术内幕】

MySQL之技术内幕 1.MVCC模式2. 实现mvcc模式的基础点3.MySQL锁的类型4. 谈谈分库分表5. 分表后的id咋么保证唯一性呢&#xff1f;6. 分表后非sharding key的查询咋么处理的&#xff1f; 1.MVCC模式 MVCC, 是multi-version concurrency control的缩写&#xff0c;即多版本并发控…

基于RK3588,AI边缘模块,单片6TOPS,可集群堆叠,Mixtile Blade 3

Mixtile Blade 3 是一款经济实惠、节能的 SBC&#xff0c;围绕下一代 8 纳米瑞芯微 RK3588 处理器构建。它非常适合快速开发、AI 应用程序原型设计和边缘计算&#xff0c;允许您集群多个 Mixtile Blade 3 SBC 以扩展您的部署。 硬件布局正反面 开箱即用的 Mixtile Blade 3 是一…

Jordan标准型

Jordan(若尔当)标准型知识梳理 szmike Keep curious 已关注 raDar 等 634 人赞同了该文章 本文主要介绍什么是Jordan标准型以及怎么把一个矩阵化为Jordan标准型。 一&#xff0c;Jordan标准型的定义 矩阵 J 除了主对角线和主对角线上方元素之外&#xff0c;其余都是0&…

漫步者头戴式耳机怎么样?漫步者、西圣、索尼三大耳机测评对比

自头戴式耳机诞生以来&#xff0c;凭借其出色的音质表现和时尚造型&#xff0c;迅速赢得了音乐爱好者的青睐。头戴式耳机不仅能够带来更加沉浸的听觉体验&#xff0c;还具备较强的降噪功能&#xff0c;让用户在嘈杂环境中依然能专注于音乐世界。 与入耳式耳机相比&#xff0c;…

AIGC生图基础知识

一、引言 AIGC&#xff0c;即AI-Generated Content&#xff0c;是一种利用大型预训练模型如生成对抗网络&#xff08;GAN&#xff09;、扩散网络&#xff08;Diffusion&#xff09;和语言大模型&#xff08;Transformer&#xff09;等人工智能技术&#xff0c;通过对大量数据进…

通过springcloud gateway优雅的进行springcloud oauth2认证和权限控制

代码地址 如果对你有帮助请给个start&#xff0c;本项目会持续更新&#xff0c;目标是做一个可用的快速微服务开发平台&#xff0c;成为接私活&#xff0c;毕设的开发神器&#xff0c; 欢迎大神们多提意见和建议 使用的都是spring官方最新的版本&#xff0c;版本如下&#xff1…

样本册3D翻页电子版和印刷版同时拥有是一种什么体验

​在数字化时代&#xff0c;样本册3D翻页电子版的兴起&#xff0c;让传统印刷版样本册面临着前所未有的挑战。与此同时&#xff0c;许多企业也开始尝试将两者相结合&#xff0c;以满足更多元化的市场需求。那么&#xff0c;拥有一份既具备数字化优势&#xff0c;又保留传统印刷…

生信初学者教程(一):欢迎

文章目录 配套数据R包版本安装包版权答疑在生物信息学(生信)领域,随着高通量测序技术的不断发展,大量数据涌现,为科研工作者提供了丰富的资源。然而,对于初学者而言,如何从海量的数据中挖掘有价值的信息,并开展一个完整的生信项目,仍然是一个挑战。目前,市面上针对初…

PACKMOL 一:手把手教你用Linux安装 packmol

文章目录 1. PACKMOL介绍PACKMOL的主要用途&#xff1a;使用场景&#xff1a;优点&#xff1a; 2. PACKMO安装3. PACKMO验证结束语 1. PACKMOL介绍 PACKMOL 是一个开源软件&#xff0c;用于生成分子动力学模拟所需的初始结构。它的主要功能是根据用户定义的几何约束&#xff0…

Excel--WPS 函数与公式技巧(轻松搞定各类排名)

一、直接按成绩或数值的排序&#xff08;rank函数轻松搞定&#xff09; 以上函数非常简单&#xff0c;记住两点&#xff1a; 1.rank排名同分作为同一名次&#xff0c;后面的名次需要占位&#xff0c;如&#xff0c;以上两个70分&#xff0c;同为第8名&#xff0c;那么第9名将被…

局域网变压器市场价值

2024 年全球局域网变压器市场价值为 3.056 亿美元&#xff0c;预计到 2030 年将达到 4.426 亿美元&#xff0c;2024-2030 年的复合年增长率为 5.4%。 局域网变压器市场包括用于改变电信号电压或格式的产品&#xff0c;以改善和简化局域网 (LAN) 上的数据传输。这些变压器对于保…

01_WebRtc_一对一视频通话

文章目录 通话网页的设计客户端实现Web的API 服务端实现 2024-9-20 很久没有写博客啦&#xff0c;回顾总结这段时间的成果&#xff0c; 写下博客放松下&#xff08;开始偷懒啦&#xff09;主要内容&#xff1a;实现网页&#xff08;html&#xff09;打开摄像头并显示到页面需要…

《 LiteFlow 规则引擎(1) - 入门篇》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

品牌力是什么?如何评估企业品牌影响力?

品牌影响力&#xff0c;其实就是指品牌在消费者心智中所占据的位置&#xff0c;以及它对消费者购买决策和行为的影响力。如果一个企业的品牌影响力越强&#xff0c;它在消费者心中的印象就越深刻&#xff0c;能够更有效地驱动消费者的购买行为&#xff0c;形成品牌忠诚度&#…

Windows用管理员运行cmd命令后无法切换盘符

解决方法&#xff1a;在你的切换的盘符前面加上/d&#xff0c;如原本命令是&#xff1a;cd d:\。变为&#xff1a;cd /d d:\。