<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>RiverMao</title>
    <link>https://rivermao.com/</link>
    <description>Recent content on RiverMao</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 11 Jul 2025 10:19:25 +0800</lastBuildDate>
    <atom:link href="https://rivermao.com/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Java Launcher Introduction</title>
      <link>https://rivermao.com/program/java-launcher/</link>
      <pubDate>Fri, 11 Jul 2025 10:19:25 +0800</pubDate>
      <guid>https://rivermao.com/program/java-launcher/</guid>
      <description>&lt;h2 id=&#34;150x150logo-smallpng-java-launcher&#34;&gt;&lt;img src=&#34;https://tc.z.wiki/autoupload/f/orCzaWOvKzgYH1bdiGU7RymIkHMchKbLor7dh3rvZ9Gyl5f0KlZfm6UsKj-HyTuv/20250711/MFdm/150X150/logo-small.png&#34; alt=&#34;150X150/logo-small.png&#34;&gt; Java Launcher&lt;/h2&gt;&#xA;&lt;h2 id=&#34;-中文介绍&#34;&gt;⭐️ &lt;a href=&#34;https://rivermao.com/program/java-launcher-zh/&#34;&gt;中文介绍&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Java Launcher is a powerful and intuitive VS Code extension for discovering, running, managing, and debugging your Java applications. Its design is inspired by the seamless run and debug experience in JetBrains IntelliJ IDEA.&lt;/p&gt;&#xA;&lt;p&gt;Say goodbye to the tedious work of manually editing &lt;code&gt;launch.json&lt;/code&gt;. Java Launcher automatically discovers all runnable entry points in your project—including &lt;code&gt;main&lt;/code&gt; methods, Spring Boot applications, and tests—and displays them in a dedicated view in the Activity Bar. You can even start, restart, or stop your entire microservice stack with a single click.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Java Launcher 中文介绍</title>
      <link>https://rivermao.com/program/java-launcher-zh/</link>
      <pubDate>Fri, 11 Jul 2025 10:19:25 +0800</pubDate>
      <guid>https://rivermao.com/program/java-launcher-zh/</guid>
      <description>&lt;h2 id=&#34;150x150logo-smallpng-java-launcher&#34;&gt;&lt;img src=&#34;https://tc.z.wiki/autoupload/f/orCzaWOvKzgYH1bdiGU7RymIkHMchKbLor7dh3rvZ9Gyl5f0KlZfm6UsKj-HyTuv/20250711/MFdm/150X150/logo-small.png&#34; alt=&#34;150X150/logo-small.png&#34;&gt; Java Launcher&lt;/h2&gt;&#xA;&lt;h2 id=&#34;-instructions-in-english&#34;&gt;⭐️ &lt;a href=&#34;https://rivermao.com/program/java-launcher/&#34;&gt;Instructions in English&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Java Launcher 是一款功能强大、操作直观的 VS Code 插件，用于发现、运行、管理和调试您的 Java 应用。其设计灵感来源于 JetBrains IntelliJ IDEA 中流畅的运行和调试体验。&lt;/p&gt;&#xA;&lt;p&gt;告别手动编辑 launch.json 的繁琐工作。Java Launcher 会自动发现您项目中所有可运行的入口点——包括 main 方法、Spring Boot 应用和测试——并将它们展示在活动栏的一个专属视图中。您甚至可以一键启动,重启, 停止整个微服务技术栈。&lt;/p&gt;</description>
    </item>
    <item>
      <title>知识图谱与图数据库Neo4j--Part03</title>
      <link>https://rivermao.com/program/knowledge_graph_003/</link>
      <pubDate>Sat, 16 Nov 2024 21:03:44 +0800</pubDate>
      <guid>https://rivermao.com/program/knowledge_graph_003/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://rivermao.com/program/knowledge_graph_002/&#34;&gt;知识图谱与图数据库Neo4j&amp;ndash;Part02&lt;/a&gt; &amp;lt;&amp;mdash; Part02&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h1 id=&#34;spring-data-neo4jsdn&#34;&gt;Spring Data Neo4j(SDN)&lt;/h1&gt;&#xA;&lt;p&gt;&lt;em&gt;可以说目前这个系列就是为了&lt;strong&gt;SDN&lt;/strong&gt;这点醋才包的饺子, 笔者写到这里的时候已经踩过了太多的坑&lt;/em&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;版本&#34;&gt;版本&lt;/h2&gt;&#xA;&lt;p&gt;如果不想和不久前的我一样痛苦,版本就跟我保持一致&lt;/p&gt;</description>
    </item>
    <item>
      <title>知识图谱与图数据库Neo4j--Part02</title>
      <link>https://rivermao.com/program/knowledge_graph_002/</link>
      <pubDate>Sat, 16 Nov 2024 20:32:11 +0800</pubDate>
      <guid>https://rivermao.com/program/knowledge_graph_002/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://rivermao.com/program/knowledge_graph_001/&#34;&gt;知识图谱与图数据库Neo4j&amp;ndash;Part01&lt;/a&gt; &amp;lt;&amp;mdash; Part01&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;一-图数据库和关系型db的对比&#34;&gt;一. 图数据库和关系型DB的对比&lt;/h2&gt;&#xA;&lt;p&gt;从技术上来说, 用关系型数据库(如pgSQL, MariaDB)来存储知识图谱,是完全没问题的, 但一旦知识图谱变复杂,用传统的[&lt;strong&gt;关系数据存储&lt;/strong&gt;], 查询效率会显著低于[&lt;strong&gt;图数据库&lt;/strong&gt;], 在一些涉及到2,3度的关联查询场景, 图数据库能把查询效率提升几千倍甚至几百万倍.&#xA;而且基于图的存储在设计上会非常灵活, 一般只需要有局部的改动即可, 当场景数据规模较大时, 建议使用图数据库来进行存储&lt;/p&gt;</description>
    </item>
    <item>
      <title>知识图谱与图数据库Neo4j--Part01</title>
      <link>https://rivermao.com/program/knowledge_graph_001/</link>
      <pubDate>Sat, 16 Nov 2024 19:46:11 +0800</pubDate>
      <guid>https://rivermao.com/program/knowledge_graph_001/</guid>
      <description>&lt;h1 id=&#34;知识图谱&#34;&gt;知识图谱&lt;/h1&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;{  此Part较枯燥, 看不下去可以直接看Part02&amp;ndash;&amp;gt; &lt;a href=&#34;https://rivermao.com/program/knowledge_graph_002/&#34;&gt;知识图谱与图数据库Neo4j&amp;ndash;Part02&lt;/a&gt;   }&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;1-什么是知识图谱&#34;&gt;1. 什么是知识图谱&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;基本概念: 知识图谱是一种结构化的语义知识库, 用于快速描述物理世界中的概念及其相互关系. 它通常以图形结构的方式来直观展示实体(对象, 事件, 状况或概念)及其关系. 知识图谱的基本组成为: “&lt;strong&gt;实体&lt;/strong&gt;&amp;mdash;-&amp;gt;&lt;strong&gt;关系&lt;/strong&gt;&amp;mdash;-&amp;gt;&lt;strong&gt;实体&lt;/strong&gt;”三元组, 这些信息常常存储在图形数据库中.&lt;/li&gt;&#xA;&lt;li&gt;直观描述: 知识图谱本质为存储实体之间的复杂关系,并让资源更易于计算,理解和评价&lt;/li&gt;&#xA;&lt;li&gt;目前的应用:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;搜索结果优化&lt;/li&gt;&#xA;&lt;li&gt;电商智能推荐与智能客服&lt;/li&gt;&#xA;&lt;li&gt;金融风控分析&lt;/li&gt;&#xA;&lt;li&gt;公安情报分析与反欺诈&lt;/li&gt;&#xA;&lt;li&gt;自然语言分析&lt;/li&gt;&#xA;&lt;li&gt;…&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;组成: 知识图谱由模式层和数据层两部分组成.&#xA;1).模式层: 存储着经过提炼的知识&#xA;2).数据层: 存储着事实&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;2-知识图谱的原始数据类型和存储方式&#34;&gt;2. 知识图谱的原始数据类型和存储方式&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;原始数据结构: 知识图谱的原始数据结构一般来说有三类:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;结构化数据(关系型数据库, 链接数据等)&lt;/li&gt;&#xA;&lt;li&gt;半结构化数据(XML, JSON, 百科等)&lt;/li&gt;&#xA;&lt;li&gt;非结构化数据(图片,音频,视频等)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;存储方式:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;通过RDF(资源描述框架)这样的存储格式来存储, 比如Jena&lt;/li&gt;&#xA;&lt;li&gt;使用图数据库来存储, 常用的有Neo4j&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;下一Part介绍Neo4j: &lt;a href=&#34;https://rivermao.com/program/knowledge_graph_002/&#34;&gt;Part02&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Git中的Git-SVN使用指南</title>
      <link>https://rivermao.com/program/git-svn-helper/</link>
      <pubDate>Thu, 26 Sep 2024 19:30:49 +0800</pubDate>
      <guid>https://rivermao.com/program/git-svn-helper/</guid>
      <description>&lt;blockquote&gt;&#xA;&lt;p&gt;献给所有习惯使用了Git但不得不使用SVN的人们, 比如我&lt;/p&gt;&#xA;&lt;p&gt;使用git-svn拉下来的仓库本质上是一个git仓库, 但所有push和fetch都必须使用&lt;code&gt;git-svn&lt;/code&gt;而不是&lt;code&gt;git&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Mybatis &amp; Spring Data Jpa 多数据源配置</title>
      <link>https://rivermao.com/program/orm-multiple-datasource/</link>
      <pubDate>Fri, 13 Sep 2024 09:07:06 +0800</pubDate>
      <guid>https://rivermao.com/program/orm-multiple-datasource/</guid>
      <description>&lt;h2 id=&#34;mybatis多数据源&#34;&gt;Mybatis多数据源&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Master:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.config.hikari.mybatis&#xA;&#xA;import com.xxx.xxx.config.hikari.map.specific.MasterMyHikariSetting&#xA;import com.xxx.xxx.util.HikariSetting2ConfigUtils&#xA;import com.zaxxer.hikari.HikariDataSource&#xA;import org.apache.ibatis.session.SqlSessionFactory&#xA;import org.mybatis.spring.SqlSessionFactoryBean&#xA;import org.mybatis.spring.SqlSessionTemplate&#xA;import org.mybatis.spring.annotation.MapperScan&#xA;import org.slf4j.Logger&#xA;import org.slf4j.LoggerFactory&#xA;import org.springframework.beans.factory.annotation.Qualifier&#xA;import org.springframework.context.annotation.Bean&#xA;import org.springframework.context.annotation.Configuration&#xA;import org.springframework.context.annotation.Primary&#xA;import org.springframework.jdbc.datasource.DataSourceTransactionManager&#xA;import javax.sql.DataSource&#xA;&#xA;&#xA;/**&#xA; * Master数据源加载&#xA; * @author: River&#xA; * @version: 1.0&#xA; */&#xA;@Configuration&#xA;//扫receive包&#xA;@MapperScan(basePackages = [&amp;quot;com.xxx.xxx.mapper.master&amp;quot;], sqlSessionFactoryRef = &amp;quot;masterSqlSessionFactory&amp;quot;)&#xA;class MasterDatasourceConfig {&#xA;    //获取日志对象&#xA;    val log: Logger = LoggerFactory.getLogger(this.javaClass)&#xA;&#xA;    //初始化第一个数据源(master/接收方)&#xA;    @Bean(name = [&amp;quot;materDatasource&amp;quot;])&#xA;    @Primary&#xA;    fun masterDatasource(myHikariSetting: MasterMyHikariSetting): DataSource {&#xA;        log.info(&amp;quot;正在初始化Master数据源...&amp;quot;)&#xA;        return HikariDataSource(HikariSetting2ConfigUtils.mySetting2Config(myHikariSetting))&#xA;    }&#xA;&#xA;    /**&#xA;     * mybatis sqlSession&#xA;     */&#xA;    @Bean(name = [&amp;quot;masterSqlSessionFactory&amp;quot;])&#xA;    @Primary&#xA;    fun sqlSessionFactory(@Qualifier(&amp;quot;materDatasource&amp;quot;) dataSource: DataSource): SqlSessionFactory? {&#xA;        val sqlBean = SqlSessionFactoryBean()&#xA;        sqlBean.setDataSource(dataSource)&#xA;//        val resolver = PathMatchingResourcePatternResolver()&#xA;//        sqlBean.setMapperLocations(*resolver.getResources(&amp;quot;classpath:mapper/*.xml&amp;quot;))&#xA;        return sqlBean.`object`&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;masterTransactionManager&amp;quot;])&#xA;    @Primary&#xA;    fun transactionManager(@Qualifier(&amp;quot;materDatasource&amp;quot;) dataSource: DataSource): DataSourceTransactionManager {&#xA;        return DataSourceTransactionManager(dataSource)&#xA;    }&#xA;&#xA;    @Primary&#xA;    @Bean(name = [&amp;quot;masterSqlSessionTemplate&amp;quot;])&#xA;    fun sqlSessionTemplate(@Qualifier(&amp;quot;masterSqlSessionFactory&amp;quot;) sqlSessionFactory: SqlSessionFactory): SqlSessionTemplate {&#xA;        log.info(&amp;quot;Master数据源SqlSessionFactory创建成功...&amp;quot;)&#xA;        return SqlSessionTemplate(sqlSessionFactory)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Next:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.config.hikari.mybatis&#xA;&#xA;import com.xxx.xxx.kotlin.config.hikari.map.specific.SourceFirstMyHikariSetting&#xA;import com.xxx.xxx.kotlin.util.HikariSetting2ConfigUtils&#xA;import com.zaxxer.hikari.HikariDataSource&#xA;import org.apache.ibatis.session.SqlSessionFactory&#xA;import org.mybatis.spring.SqlSessionFactoryBean&#xA;import org.mybatis.spring.SqlSessionTemplate&#xA;import org.mybatis.spring.annotation.MapperScan&#xA;import org.slf4j.Logger&#xA;import org.slf4j.LoggerFactory&#xA;import org.springframework.beans.factory.annotation.Qualifier&#xA;import org.springframework.context.annotation.Bean&#xA;import org.springframework.context.annotation.Configuration&#xA;import org.springframework.jdbc.datasource.DataSourceTransactionManager&#xA;import javax.sql.DataSource&#xA;&#xA;/**&#xA; * 第一个副数据源加载&#xA; * @author River&#xA; * @since 1.0&#xA; */&#xA;@Configuration&#xA;@MapperScan(basePackages = [&amp;quot;com.xxx.xxx.mapper.first&amp;quot;], sqlSessionFactoryRef = &amp;quot;sourceFirstSqlSessionFactory&amp;quot;)&#xA;class SourceFirstDatasourceConfig {&#xA;    //获取日志对象&#xA;    val log: Logger = LoggerFactory.getLogger(this.javaClass)&#xA;    &#xA;    @Bean(name = [&amp;quot;sourceFirstDatasource&amp;quot;])&#xA;    fun sourceFirstDatasource(myHikariSetting: SourceFirstMyHikariSetting): DataSource {&#xA;        log.info(&amp;quot;正在初始化第一个副数据源...&amp;quot;)&#xA;        return HikariDataSource(HikariSetting2ConfigUtils.mySetting2Config(myHikariSetting))&#xA;    }&#xA;&#xA;    /**&#xA;     * mybatis sqlSession&#xA;     */&#xA;    @Bean(name = [&amp;quot;sourceFirstSqlSessionFactory&amp;quot;])&#xA;    fun sqlSessionFactory(@Qualifier(&amp;quot;sourceFirstDatasource&amp;quot;) dataSource: DataSource): SqlSessionFactory? {&#xA;        val sqlBean = SqlSessionFactoryBean()&#xA;        sqlBean.setDataSource(dataSource)&#xA;//        val resolver = PathMatchingResourcePatternResolver()&#xA;//        sqlBean.setMapperLocations(*resolver.getResources(&amp;quot;classpath:mapper/*.xml&amp;quot;))&#xA;        return sqlBean.`object`&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;sourceFirstTransactionManager&amp;quot;])&#xA;    fun transactionManager(@Qualifier(&amp;quot;sourceFirstDatasource&amp;quot;) dataSource: DataSource): DataSourceTransactionManager {&#xA;        return DataSourceTransactionManager(dataSource)&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;sourceFirstSqlSessionTemplate&amp;quot;])&#xA;    fun sqlSessionTemplate(@Qualifier(&amp;quot;sourceFirstSqlSessionFactory&amp;quot;) sqlSessionFactory: SqlSessionFactory): SqlSessionTemplate {&#xA;        log.info(&amp;quot;第一个副数据源SqlSessionFactory创建成功...&amp;quot;)&#xA;        return SqlSessionTemplate(sqlSessionFactory)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;spring-data-jpa-多数据源&#34;&gt;Spring Data Jpa 多数据源&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Primary:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.config.hikari.jpa&#xA;&#xA;import com.xxx.xxx.kotlin.config.hikari.map.specific.MasterMyHikariSetting&#xA;import com.xxx.xxx.kotlin.util.HikariSetting2ConfigUtils&#xA;import com.zaxxer.hikari.HikariDataSource&#xA;import org.slf4j.Logger&#xA;import org.slf4j.LoggerFactory&#xA;import org.springframework.beans.factory.annotation.Autowired&#xA;import org.springframework.beans.factory.annotation.Qualifier&#xA;import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties&#xA;import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings&#xA;import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties&#xA;import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder&#xA;import org.springframework.context.annotation.Bean&#xA;import org.springframework.context.annotation.Configuration&#xA;import org.springframework.context.annotation.Primary&#xA;import org.springframework.data.jpa.repository.config.EnableJpaRepositories&#xA;import org.springframework.orm.jpa.JpaTransactionManager&#xA;import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean&#xA;import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager&#xA;import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter&#xA;import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter&#xA;import org.springframework.transaction.PlatformTransactionManager&#xA;import org.springframework.transaction.annotation.EnableTransactionManagement&#xA;import javax.persistence.EntityManager&#xA;import javax.sql.DataSource&#xA;&#xA;&#xA;@Configuration&#xA;@EnableTransactionManagement&#xA;@EnableJpaRepositories(&#xA;    entityManagerFactoryRef = &amp;quot;entityManagerFactoryPrimary&amp;quot;,&#xA;    transactionManagerRef = &amp;quot;transactionManagerPrimary&amp;quot;,&#xA;    basePackages = [&amp;quot;com.xxx.xxx.kotlin.repository.first&amp;quot;]&#xA;)&#xA;class PrimaryDatasourceConfig {&#xA;    //获取日志对象&#xA;    val log: Logger = LoggerFactory.getLogger(this::class.java)&#xA;&#xA;    @Autowired&#xA;    private lateinit var jpaProperties: JpaProperties&#xA;&#xA;    @Autowired&#xA;    private lateinit var hibernateProperties: HibernateProperties&#xA;&#xA;    @Autowired(required = false)&#xA;    private val persistenceUnitManager: PersistenceUnitManager? = null&#xA;&#xA;&#xA;    @Bean(name = [&amp;quot;primaryDatasource&amp;quot;])&#xA;    fun primaryDatasource(myHikariSetting: MasterMyHikariSetting): DataSource {&#xA;        log.info(&amp;quot;正在初始化JPA master数据源...&amp;quot;)&#xA;        return HikariDataSource(HikariSetting2ConfigUtils.mySetting2Config(myHikariSetting))&#xA;    }&#xA;&#xA;    private fun getVendorProperties(): Map&amp;lt;String?, Any?&amp;gt;? {&#xA;        return hibernateProperties.determineHibernateProperties(jpaProperties.properties, HibernateSettings())&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;myEntityManagerFactoryBuilder&amp;quot;])&#xA;    fun customerEntityManagerFactoryBuilder(customerJpaProperties: JpaProperties): EntityManagerFactoryBuilder? {&#xA;        val adapter: AbstractJpaVendorAdapter = HibernateJpaVendorAdapter()&#xA;        return EntityManagerFactoryBuilder(&#xA;            adapter,&#xA;            customerJpaProperties.properties, persistenceUnitManager&#xA;        )&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;entityManagerPrimary&amp;quot;])&#xA;    @Primary&#xA;    fun entityManager(@Qualifier(&amp;quot;myEntityManagerFactoryBuilder&amp;quot;)builder: EntityManagerFactoryBuilder, @Qualifier(&amp;quot;primaryDatasource&amp;quot;) datasource: DataSource): EntityManager? {&#xA;        return entityManagerFactoryPrimary(builder, datasource).getObject()!!.createEntityManager()&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;entityManagerFactoryPrimary&amp;quot;])&#xA;    @Primary&#xA;    fun entityManagerFactoryPrimary(@Qualifier(&amp;quot;myEntityManagerFactoryBuilder&amp;quot;)builder: EntityManagerFactoryBuilder, @Qualifier(&amp;quot;primaryDatasource&amp;quot;) datasource: DataSource): LocalContainerEntityManagerFactoryBean {&#xA;        return builder&#xA;            .dataSource(datasource)&#xA;            .packages(&amp;quot;com.xxx.xxx.kotlin.entity.master&amp;quot;) //设置实体类所在位置&#xA;            .persistenceUnit(&amp;quot;primary&amp;quot;)&#xA;            .properties(getVendorProperties())&#xA;            .build()&#xA;    }&#xA;    @Bean(name = [&amp;quot;transactionManagerPrimary&amp;quot;])&#xA;    @Primary&#xA;    fun transactionManagerPrimary(@Qualifier(&amp;quot;myEntityManagerFactoryBuilder&amp;quot;)builder: EntityManagerFactoryBuilder, @Qualifier(&amp;quot;primaryDatasource&amp;quot;) datasource: DataSource): PlatformTransactionManager? {&#xA;        return JpaTransactionManager(entityManagerFactoryPrimary(builder, datasource).getObject()!!)&#xA;    }&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Next:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.config.hikari.jpa&#xA;&#xA;import com.xxx.xxx.kotlin.config.hikari.map.specific.SourceSecondMyHikariSetting&#xA;import com.xxx.xxx.kotlin.util.HikariSetting2ConfigUtils&#xA;import com.zaxxer.hikari.HikariDataSource&#xA;import org.slf4j.Logger&#xA;import org.slf4j.LoggerFactory&#xA;import org.springframework.beans.factory.annotation.Autowired&#xA;import org.springframework.beans.factory.annotation.Qualifier&#xA;import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties&#xA;import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings&#xA;import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties&#xA;import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder&#xA;import org.springframework.context.annotation.Bean&#xA;import org.springframework.context.annotation.Configuration&#xA;import org.springframework.data.jpa.repository.config.EnableJpaRepositories&#xA;import org.springframework.orm.jpa.JpaTransactionManager&#xA;import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean&#xA;import org.springframework.transaction.PlatformTransactionManager&#xA;import org.springframework.transaction.annotation.EnableTransactionManagement&#xA;import javax.persistence.EntityManager&#xA;import javax.sql.DataSource&#xA;&#xA;@Configuration&#xA;@EnableTransactionManagement&#xA;@EnableJpaRepositories(&#xA;    entityManagerFactoryRef = &amp;quot;entityManagerFactorySecondary&amp;quot;,&#xA;    transactionManagerRef = &amp;quot;transactionManagerSecondary&amp;quot;,&#xA;    basePackages = [&amp;quot;com.xxx.xxx.kotlin.repository.second&amp;quot;]&#xA;)&#xA;class SecondaryDatasourceConfig {&#xA;    //获取日志对象&#xA;    val log: Logger = LoggerFactory.getLogger(this::class.java)&#xA;&#xA;    @Autowired&#xA;    private lateinit var jpaProperties: JpaProperties&#xA;&#xA;    @Autowired&#xA;    private lateinit var hibernateProperties: HibernateProperties&#xA;&#xA;    @Bean(name = [&amp;quot;secondaryDatasource&amp;quot;])&#xA;    fun secondaryDatasource(myHikariSetting: SourceSecondMyHikariSetting): DataSource {&#xA;        log.info(&amp;quot;正在初始化JPA Second数据源...&amp;quot;)&#xA;        return HikariDataSource(HikariSetting2ConfigUtils.mySetting2Config(myHikariSetting))&#xA;    }&#xA;&#xA;    private fun getVendorProperties(): Map&amp;lt;String?, Any?&amp;gt;? {&#xA;        return hibernateProperties.determineHibernateProperties(jpaProperties.properties, HibernateSettings())&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;entityManagerSecondary&amp;quot;])&#xA;    fun entityManager(&#xA;        builder: EntityManagerFactoryBuilder,&#xA;        @Qualifier(&amp;quot;secondaryDatasource&amp;quot;) datasource: DataSource&#xA;    ): EntityManager? {&#xA;        return entityManagerFactorySecondary(builder, datasource).getObject()!!.createEntityManager()&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;entityManagerFactorySecondary&amp;quot;])&#xA;    fun entityManagerFactorySecondary(&#xA;        builder: EntityManagerFactoryBuilder,&#xA;        @Qualifier(&amp;quot;secondaryDatasource&amp;quot;) datasource: DataSource&#xA;    ): LocalContainerEntityManagerFactoryBean {&#xA;        return builder&#xA;            .dataSource(datasource)&#xA;            .packages(&amp;quot;com.xxx.xxx.kotlin.entity.second&amp;quot;) //设置实体类所在位置&#xA;            .persistenceUnit(&amp;quot;secondary&amp;quot;)&#xA;            .properties(getVendorProperties())&#xA;            .build()&#xA;    }&#xA;&#xA;    @Bean(name = [&amp;quot;transactionManagerSecondary&amp;quot;])&#xA;    fun transactionManagerSecondary(&#xA;        builder: EntityManagerFactoryBuilder,&#xA;        @Qualifier(&amp;quot;secondaryDatasource&amp;quot;) datasource: DataSource&#xA;    ): PlatformTransactionManager? {&#xA;        return JpaTransactionManager(entityManagerFactorySecondary(builder, datasource).getObject()!!)&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;工具类与其他实体&#34;&gt;工具类与其他实体&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;MasterMyHikariSetting&lt;/code&gt; (其他以MyHikariSetting结尾的类与此类似,父类&lt;code&gt;BaseMyHikariSetting&lt;/code&gt;属性与此相同):&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.config.hikari.map.specific&#xA;&#xA;import com.xxx.xxx.kotlin.config.hikari.map.BaseMyHikariSetting&#xA;import com.xxx.xxx.kotlin.config.factory.YamlPropertySourceFactory&#xA;import org.springframework.boot.context.properties.ConfigurationProperties&#xA;import org.springframework.context.annotation.Configuration&#xA;import org.springframework.context.annotation.PropertySource&#xA;import java.util.*&#xA;&#xA;/**&#xA; * master配置实体&#xA; */&#xA;@Configuration&#xA;@PropertySource(value = [&amp;quot;classpath:datasources/datasources.yml&amp;quot;], factory = YamlPropertySourceFactory::class)&#xA;@ConfigurationProperties(prefix = &amp;quot;spring.datasources.master.hikari&amp;quot;)&#xA;class MasterMyHikariSetting : BaseMyHikariSetting(){&#xA;    override var maximumPoolSize: Int? = null&#xA;    override var idleTimeout: Long? = null&#xA;    override var maxLifetime: Long? = null&#xA;    override var dataSourceProperties: Properties? = null&#xA;    override var driverClassName: String? = null&#xA;    override var jdbcUrl: String? = null&#xA;    override var username: String? = null&#xA;    override var password: String? = null&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;HikariSetting2ConfigUtils&lt;/code&gt;:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-kotlin&#34;&gt;package com.xxx.xxx.kotlin.util&#xA;&#xA;import com.xxx.xxx.kotlin.config.hikari.map.BaseMyHikariSetting&#xA;import com.zaxxer.hikari.HikariConfig&#xA;&#xA;/**&#xA; * Hikari数据源配置工具类&#xA; * @author River&#xA; * @since 1.0&#xA; */&#xA;class HikariSetting2ConfigUtils {&#xA;    companion object {&#xA;        /**&#xA;         * 自定义Hikari配置转换为标准Hikari配置&#xA;         */&#xA;        fun mySetting2Config(baseSetting: BaseMyHikariSetting): HikariConfig {&#xA;            val hikariConfig = HikariConfig()&#xA;            hikariConfig.driverClassName = baseSetting.driverClassName&#xA;            hikariConfig.jdbcUrl = baseSetting.jdbcUrl&#xA;            hikariConfig.username = baseSetting.username&#xA;            hikariConfig.password = baseSetting.password&#xA;            hikariConfig.maximumPoolSize = baseSetting.maximumPoolSize!!&#xA;            hikariConfig.maxLifetime = baseSetting.maxLifetime!!&#xA;            hikariConfig.idleTimeout = baseSetting.idleTimeout!!&#xA;            hikariConfig.dataSourceProperties = baseSetting.dataSourceProperties&#xA;            return hikariConfig&#xA;        }&#xA;    }&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;位于项目&lt;code&gt;resources/datasources&lt;/code&gt;目录下的&lt;code&gt;datasources.yml&lt;/code&gt;文件:&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-yml&#34;&gt;spring:&#xA;  datasources:&#xA;    #    主数据源(pg)&#xA;    master:&#xA;      hikari:&#xA;        driver-class-name: org.postgresql.Driver&#xA;        jdbc-url: jdbc:postgresql://127.0.0.1/xxx&#xA;        username: postgres&#xA;        password: testpostgres&#xA;        maximum-pool-size: 20 &#xA;        max-lifetime: 30000&#xA;        idle-timeout: 30000&#xA;        data-source-properties:&#xA;          prepStmtCacheSize: 250&#xA;          prepStmtCacheSqlLimit: 2048&#xA;          cachePrepStmts: true&#xA;          useServerPrepStmts: true&#xA;    #    access数据源&#xA;    first:&#xA;      hikari:&#xA;        driver-class-name: net.ucanaccess.jdbc.UcanaccessDriver&#xA;        jdbc-url: jdbc:ucanaccess:////xxx/xxx/xxx.mdb&#xA;        username:&#xA;        password:&#xA;        maximum-pool-size: 20&#xA;        max-lifetime: 30000&#xA;        idle-timeout: 30000&#xA;        data-source-properties:&#xA;          prepStmtCacheSize: 250&#xA;          prepStmtCacheSqlLimit: 2048&#xA;          cachePrepStmts: true&#xA;          useServerPrepStmts: true&#xA;    second:&#xA;      hikari:&#xA;        driver-class-name: org.postgresql.Driver&#xA;        jdbc-url: jdbc:postgresql://127.0.0.1:5432/xxx&#xA;        username: postgres&#xA;        password: postgres&#xA;        maximum-pool-size: 20&#xA;        max-lifetime: 30000&#xA;        idle-timeout: 30000&#xA;        data-source-properties:&#xA;          prepStmtCacheSize: 250&#xA;          prepStmtCacheSqlLimit: 2048&#xA;          cachePrepStmts: true&#xA;          useServerPrepStmts: true&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;tip&#34;&gt;Tip:&lt;/h2&gt;&#xA;&lt;p&gt;如果在一个项目中mybatis和spring data jpa同时开启了多数据源,在Spring的事务注解中需指定当前事务管理bean&lt;/p&gt;</description>
    </item>
    <item>
      <title>有向图的邻接矩阵表示与路径可达分析</title>
      <link>https://rivermao.com/program/graph-matrix-alg/</link>
      <pubDate>Thu, 12 Sep 2024 14:23:49 +0800</pubDate>
      <guid>https://rivermao.com/program/graph-matrix-alg/</guid>
      <description>&lt;h2 id=&#34;数据结构&#34;&gt;数据结构&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Node&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import lombok.AllArgsConstructor;&#xA;import lombok.Builder;&#xA;import lombok.Data;&#xA;import lombok.NoArgsConstructor;&#xA;&#xA;/**&#xA; * 用于图的邻接矩阵与搜索算法的数据结构, 只保留唯一标识这一种属性,减少内存开销&#xA; * @author rxz&#xA; */&#xA;@Data&#xA;@Builder&#xA;@AllArgsConstructor&#xA;@NoArgsConstructor&#xA;public class Node&amp;lt;T&amp;gt; {&#xA;    T pre;&#xA;    T after;&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Pair&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import lombok.AllArgsConstructor;&#xA;import lombok.Data;&#xA;&#xA;/**&#xA; * 放置两个平级数据, 此对象用于推入栈或加入队列, 简化算法可读性&#xA; * @param &amp;lt;K&amp;gt; /&#xA; * @param &amp;lt;V&amp;gt; /&#xA; */&#xA;@Data&#xA;@AllArgsConstructor&#xA;public class Pair&amp;lt;K, V&amp;gt; {&#xA;    private K key;&#xA;    private V value;&#xA;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;GraphMatrixEntity&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import lombok.Data;&#xA;import lombok.extern.slf4j.Slf4j;&#xA;&#xA;import java.io.Serializable;&#xA;import java.util.List;&#xA;&#xA;/**&#xA; * 有向图的邻接矩阵对象&#xA; * @param &amp;lt;T&amp;gt; Node节点的类型 一般为Long&#xA; * @param &amp;lt;K&amp;gt; 原始对象集合的类型&#xA; */&#xA;@Slf4j&#xA;@Data&#xA;public class GraphMatrixEntity&amp;lt;T,K&amp;gt; implements Serializable {&#xA;    /**&#xA;     * 原始node集合&#xA;     */&#xA;    private List&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; nodes;&#xA;&#xA;    /**&#xA;     * 邻接矩阵对照尺, 是一个线性表&#xA;     */&#xA;    private List&amp;lt;T&amp;gt; standardRuler;&#xA;&#xA;    /**&#xA;     * 有向图的邻接矩阵表示&#xA;     */&#xA;    private int[][] graph;&#xA;&#xA;    /**&#xA;     * 有向图的所有头节点&#xA;     */&#xA;    private List&amp;lt;Integer&amp;gt; headNodeIndex;&#xA;&#xA;    /**&#xA;     * 有向图的所有尾节点&#xA;     */&#xA;    private List&amp;lt;Integer&amp;gt; tailNodeIndex;&#xA;&#xA;    /**&#xA;     * 原始集合(此数据结构在算法中不会被赋值,请注意判空)&#xA;     */&#xA;    private List&amp;lt;K&amp;gt; rawList;&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 id=&#34;邻接矩阵转换与路径可达性分析&#34;&gt;邻接矩阵转换与路径可达性分析&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-java&#34;&gt;import cn.hutool.core.collection.CollUtil;&#xA;import lombok.extern.slf4j.Slf4j;&#xA;&#xA;import java.util.*;&#xA;&#xA;/**&#xA; * 图的邻接矩阵转换算法与基于广度优先搜算法的路径可达节点查找算法实现&#xA; * 使用此算法时必须声明泛型!&#xA; *&#xA; * @param &amp;lt;T&amp;gt; id的类型, 出入库单中总是为Long&#xA; * @author rxz&#xA; */&#xA;@Slf4j&#xA;public class GraphMatrixHandler&amp;lt;T,K&amp;gt; {&#xA;    public GraphMatrixEntity&amp;lt;T,K&amp;gt; matrixTransfer(List&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; nodeList) {&#xA;        GraphMatrixEntity&amp;lt;T,K&amp;gt; matrix = new GraphMatrixEntity&amp;lt;&amp;gt;();&#xA;        if (CollUtil.isEmpty(nodeList)) {&#xA;            return matrix;&#xA;        }&#xA;        //1. 去重nodes&#xA;        HashSet&amp;lt;Node&amp;lt;T&amp;gt;&amp;gt; nodes = new HashSet&amp;lt;&amp;gt;(nodeList);&#xA;        Set&amp;lt;T&amp;gt; allIdSet = new HashSet&amp;lt;&amp;gt;();&#xA;        //2. 将node集合转换为有向图, 用邻接矩阵的方式实现这个有向图&#xA;        // 2.1 构造一个辅助map,对node集合进行数据整理(支持null的存在)&#xA;        Map&amp;lt;T, Set&amp;lt;T&amp;gt;&amp;gt; map = new HashMap&amp;lt;&amp;gt;();&#xA;        nodes.forEach(node -&amp;gt; {&#xA;            Set&amp;lt;T&amp;gt; valueList = Optional.ofNullable(map.get(node.pre)).orElse(new HashSet&amp;lt;&amp;gt;());&#xA;            valueList.add(node.after);&#xA;            map.put(node.pre, valueList);&#xA;&#xA;            allIdSet.add(node.pre);&#xA;            allIdSet.add(node.after);&#xA;        });&#xA;        // 2.2 初始化邻接矩阵&#xA;        List&amp;lt;T&amp;gt; nodeIdList = new ArrayList&amp;lt;&amp;gt;(allIdSet);&#xA;        int size = nodeIdList.size();&#xA;        int[][] graph = new int[size][size];&#xA;        for (int i = 0; i &amp;lt; graph.length; i++) {&#xA;            //i 严格对应preList的下标&#xA;            T iElement = nodeIdList.get(i);&#xA;            Set&amp;lt;T&amp;gt; matchingSet = map.get(iElement);&#xA;            for (int j = 0; j &amp;lt; graph[i].length; j++) {&#xA;                T jElement = nodeIdList.get(j);&#xA;                if (matchingSet != null &amp;amp;&amp;amp; matchingSet.contains(jElement)) {&#xA;                    graph[i][j] = 1;&#xA;                } else {&#xA;                    graph[i][j] = 0;&#xA;                }&#xA;            }&#xA;        }&#xA;        //3. 获取所有的头节点和尾节点(的索引)&#xA;        List&amp;lt;Integer&amp;gt; headNodeIndex = new ArrayList&amp;lt;&amp;gt;();&#xA;        List&amp;lt;Integer&amp;gt; tailNodeIndex = new ArrayList&amp;lt;&amp;gt;();&#xA;        for (int i = 0; i &amp;lt; nodeIdList.size(); i++) {&#xA;            boolean tailFlag = false;&#xA;            boolean headFlag = false;&#xA;            for (int j = 0; j &amp;lt; nodeIdList.size(); j++) {&#xA;                if (!tailFlag &amp;amp;&amp;amp; graph[i][j] == 1) {&#xA;                    tailFlag = true;&#xA;                }&#xA;                if (!headFlag &amp;amp;&amp;amp; graph[j][i] == 1) {&#xA;                    headFlag = true;&#xA;                }&#xA;            }&#xA;            if (!tailFlag) {&#xA;                tailNodeIndex.add(i);&#xA;            }&#xA;            if (!headFlag) {&#xA;                headNodeIndex.add(i);&#xA;            }&#xA;        }&#xA;&#xA;        //TODO: 如果有向图中没有任何端点(所有头和尾都存在环), 要如何处理?&#xA;&#xA;        //4. 整理结果, 返回&#xA;        matrix.setGraph(graph);&#xA;        matrix.setNodes(nodeList);&#xA;        matrix.setStandardRuler(nodeIdList);&#xA;        matrix.setHeadNodeIndex(headNodeIndex);&#xA;        matrix.setTailNodeIndex(tailNodeIndex);&#xA;&#xA;        return matrix;&#xA;    }&#xA;&#xA;    /**&#xA;     * 使用广度优先算法, 在有向图的邻接矩阵中获取某个给定节点(索引)在n步数内可以到达的所有节点的索引&#xA;     *&#xA;     * @param nodeIdList    矩阵对照尺&#xA;     * @param graph         有向图的邻接矩阵&#xA;     * @param headNodeIndex 开始节点的索引集合(在对照尺中的下标)&#xA;     * @param n             步数&#xA;     * @return Map &amp;lt; 开始节点的索引,所有可达节点在矩阵对照尺中的下标&amp;gt;&#xA;     */&#xA;    public Map&amp;lt;Integer, List&amp;lt;Integer&amp;gt;&amp;gt; findNodesWithNPossiblePaths(List&amp;lt;T&amp;gt; nodeIdList, int[][] graph, List&amp;lt;Integer&amp;gt; headNodeIndex, int n) {&#xA;        Map&amp;lt;Integer, List&amp;lt;Integer&amp;gt;&amp;gt; nPathLengthNodeIndexMap = new HashMap&amp;lt;&amp;gt;();&#xA;        if (CollUtil.isEmpty(headNodeIndex)) {&#xA;            return nPathLengthNodeIndexMap;&#xA;        }&#xA;        for (Integer index : headNodeIndex) {&#xA;            T headNode = nodeIdList.get(index);&#xA;            List&amp;lt;Integer&amp;gt; reachableNodesOnPathN = bfs(nodeIdList, graph, headNode, n);&#xA;            nPathLengthNodeIndexMap.put(index, reachableNodesOnPathN);&#xA;        }&#xA;        return nPathLengthNodeIndexMap;&#xA;    }&#xA;&#xA;    /**&#xA;     * 使用广度优先算法, 在有向图的邻接矩阵中获取某个给定节点(索引)在n步数内可以到达的所有节点的索引&#xA;     *&#xA;     * @param nodeIdList 矩阵对照尺&#xA;     * @param graph      有向图的邻接矩阵&#xA;     * @param startNode  开始节点的索引(在对照尺中的下标)&#xA;     * @param n          步数&#xA;     * @return 所有可达节点在矩阵对照尺中的下标&#xA;     */&#xA;    private List&amp;lt;Integer&amp;gt; bfs(List&amp;lt;T&amp;gt; nodeIdList, int[][] graph, T startNode, int n) {&#xA;        List&amp;lt;Integer&amp;gt; result = new ArrayList&amp;lt;&amp;gt;();&#xA;        int startIndex = nodeIdList.indexOf(startNode);&#xA;        Queue&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();&#xA;        queue.offer(new Pair&amp;lt;&amp;gt;(startIndex, 0));&#xA;&#xA;        while (!queue.isEmpty()) {&#xA;            Pair&amp;lt;Integer, Integer&amp;gt; current = queue.poll();&#xA;            int currentNodeIndex = current.getKey();&#xA;            int currentDepth = current.getValue();&#xA;&#xA;            if (currentDepth &amp;lt; n) {&#xA;                for (int j = 0; j &amp;lt; graph[currentNodeIndex].length; j++) {&#xA;                    if (graph[currentNodeIndex][j] == 1) {&#xA;                        queue.offer(new Pair&amp;lt;&amp;gt;(j, currentDepth + 1));&#xA;                    }&#xA;                }&#xA;            } else if (currentDepth == n) {&#xA;                result.add(currentNodeIndex);&#xA;            }&#xA;        }&#xA;        return result;&#xA;    }&#xA;&#xA;    /**&#xA;     * 使用广度优先搜索, 获取有向图中在给定步数m下, 可以到达给定节点(索引)的所有节点(索引)&#xA;     * @param nodeIdList 矩阵对照尺&#xA;     * @param graph 有向图的邻接矩阵&#xA;     * @param tailNodeIndex 最终到达节点的索引(在对照尺中的下标)&#xA;     * @param m 步数&#xA;     * @return 所有可出发节点在矩阵对照尺中的下标&#xA;     */&#xA;    public Map&amp;lt;Integer, List&amp;lt;Integer&amp;gt;&amp;gt; findNodesReachingCanReach(List&amp;lt;T&amp;gt; nodeIdList, int[][] graph, List&amp;lt;Integer&amp;gt; tailNodeIndex, int m) {&#xA;        Map&amp;lt;Integer, List&amp;lt;Integer&amp;gt;&amp;gt; goForwardnPathLengthNodeIndexMap = new HashMap&amp;lt;&amp;gt;();&#xA;        if (CollUtil.isEmpty(tailNodeIndex)) {&#xA;            return goForwardnPathLengthNodeIndexMap;&#xA;        }&#xA;        for (Integer index : tailNodeIndex) {&#xA;            T tailNode = nodeIdList.get(index);&#xA;            List&amp;lt;Integer&amp;gt; reachableNodesOnPathM = bfsToReachNode(nodeIdList, graph, tailNode, m);&#xA;            goForwardnPathLengthNodeIndexMap.put(index, reachableNodesOnPathM);&#xA;        }&#xA;        return goForwardnPathLengthNodeIndexMap;&#xA;    }&#xA;&#xA;&#xA;    private List&amp;lt;Integer&amp;gt; bfsToReachNode(List&amp;lt;T&amp;gt; nodeIdList, int[][] graph, T targetNode, int m) {&#xA;        List&amp;lt;Integer&amp;gt; result = new ArrayList&amp;lt;&amp;gt;();&#xA;        if (nodeIdList.isEmpty()) {&#xA;            return result;&#xA;        }&#xA;        int targetIndex = nodeIdList.indexOf(targetNode);&#xA;        Queue&amp;lt;Pair&amp;lt;Integer, Integer&amp;gt;&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();&#xA;        queue.offer(new Pair&amp;lt;&amp;gt;(targetIndex, 0));&#xA;&#xA;        while (!queue.isEmpty()) {&#xA;            Pair&amp;lt;Integer, Integer&amp;gt; current = queue.poll();&#xA;            int currentNodeIndex = current.getKey();&#xA;            int currentDepth = current.getValue();&#xA;&#xA;            if (currentDepth &amp;lt; m) {&#xA;                for (int j = 0; j &amp;lt; graph.length; j++) {&#xA;                    if (graph[j][currentNodeIndex] == 1) {&#xA;                        queue.offer(new Pair&amp;lt;&amp;gt;(j, currentDepth + 1));&#xA;                    }&#xA;                }&#xA;            } else if (currentDepth == m) {&#xA;                result.add(currentNodeIndex);&#xA;            }&#xA;        }&#xA;        return result;&#xA;    }&#xA;&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>2024-09-12记</title>
      <link>https://rivermao.com/life/2024-09-12/</link>
      <pubDate>Thu, 12 Sep 2024 12:31:30 +0800</pubDate>
      <guid>https://rivermao.com/life/2024-09-12/</guid>
      <description>&lt;h2 id=&#34;2024-09-12-重启blog&#34;&gt;&lt;em&gt;2024-09-12&lt;/em&gt; &lt;strong&gt;重启Blog&lt;/strong&gt;&lt;/h2&gt;</description>
    </item>
    <item>
      <title>Birthday_25</title>
      <link>https://rivermao.com/life/birthday-25/</link>
      <pubDate>Fri, 18 Aug 2023 19:44:30 +0800</pubDate>
      <guid>https://rivermao.com/life/birthday-25/</guid>
      <description>&lt;h2 id=&#34;无法评价的-公元2023年&#34;&gt;无法评价的: 公元2023年&lt;/h2&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;很庆幸自己依然平静的度过了25岁生日&lt;/p&gt;&#xA;&lt;p&gt;看着上一条记录生日的md&lt;/p&gt;&#xA;&lt;p&gt;感慨万千,恍如隔日&lt;/p&gt;&#xA;&lt;p&gt;愿你我都有光明的未来;&lt;/p&gt;&lt;/blockquote&gt;</description>
    </item>
    <item>
      <title>在java或kotlin中使用jna调用dll动态链接库</title>
      <link>https://rivermao.com/program/java-java-kotlin-jna-dll-call/</link>
      <pubDate>Fri, 10 Mar 2023 08:39:51 +0800</pubDate>
      <guid>https://rivermao.com/program/java-java-kotlin-jna-dll-call/</guid>
      <description>&lt;h2 id=&#34;1jna介绍&#34;&gt;1.jna介绍&lt;/h2&gt;&#xA;&lt;p&gt;Java Native Access (JNA),Github地址:&lt;a href=&#34;https://github.com/java-native-access/jna&#34;&gt;JNA&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;在仓库的README.md中有:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;JNA provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required. This functionality is comparable to Windows&amp;rsquo; Platform/Invoke and Python&amp;rsquo;s ctypes.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Compose Multiplatform自定义可下拉输入框组件</title>
      <link>https://rivermao.com/program/kotlin-compose-customtextfield/</link>
      <pubDate>Wed, 08 Mar 2023 14:39:51 +0800</pubDate>
      <guid>https://rivermao.com/program/kotlin-compose-customtextfield/</guid>
      <description>&lt;h1&gt;&lt;/h1&gt;&#xA;&lt;p&gt;compose自带库中的TextField和outlinedTextField有默认的大小,都属于Material风格的输入框,最小尺寸很大,如果要创建UI上比较紧凑的表单,就需要自定义组件了,同时让这个自定义组件也可作为下拉框来使用&lt;/p&gt;</description>
    </item>
    <item>
      <title>线性最小二乘法的参数解</title>
      <link>https://rivermao.com/program/math-normal-latest-squares/</link>
      <pubDate>Thu, 02 Mar 2023 14:09:40 +0800</pubDate>
      <guid>https://rivermao.com/program/math-normal-latest-squares/</guid>
      <description>&lt;h2 id=&#34;定义&#34;&gt;定义&lt;/h2&gt;&#xA;&lt;p&gt;最小二乘法（英语：least squares method），又称最小平方法，是一种数学优化建模方法。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便的求得未知的数据，并使得求得的数据与实际数据之间误差的平方和为最小。&lt;/p&gt;</description>
    </item>
    <item>
      <title>在PostgreSQL中使用窗口函数解决取分组后前n条数据的问题</title>
      <link>https://rivermao.com/program/pgsql-function-olap/</link>
      <pubDate>Thu, 23 Feb 2023 11:09:40 +0800</pubDate>
      <guid>https://rivermao.com/program/pgsql-function-olap/</guid>
      <description>&lt;p&gt;先描述一个业务场景:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;现有一张数据表,结构如下:&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://imgse.com/i/pSvjkVg&#34;&gt;&lt;img src=&#34;https://s1.ax1x.com/2023/02/23/pSvjkVg.png&#34; alt=&#34;pSvjkVg.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;现在要查询每个不同&lt;code&gt;number&lt;/code&gt;的最后一条(create_time)的完整记录&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;保证查询结果中的&lt;code&gt;number&lt;/code&gt;不重复&lt;/p&gt;</description>
    </item>
    <item>
      <title>Birthday_24</title>
      <link>https://rivermao.com/life/birthday-24/</link>
      <pubDate>Sun, 31 Jul 2022 19:39:30 +0800</pubDate>
      <guid>https://rivermao.com/life/birthday-24/</guid>
      <description>&lt;h2 id=&#34;happy-24th-birthday--&#34;&gt;Happy 24th birthday!  🎂&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;祝自己24岁生日快乐&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kotlin中select关键字与Channel的用法</title>
      <link>https://rivermao.com/program/kotlin-select-channel-using/</link>
      <pubDate>Fri, 08 Jul 2022 16:39:51 +0800</pubDate>
      <guid>https://rivermao.com/program/kotlin-select-channel-using/</guid>
      <description>&lt;h2 id=&#34;kotlin中channel的使用&#34;&gt;Kotlin中Channel的使用&lt;/h2&gt;&#xA;&lt;p&gt;类似&lt;em&gt;Go&lt;/em&gt;中的&lt;em&gt;Channel&lt;/em&gt;,&lt;em&gt;Kotlin&lt;/em&gt;中的&lt;em&gt;Channel&lt;/em&gt;也可以在&lt;strong&gt;协程&lt;/strong&gt;间通信&lt;/p&gt;&#xA;&lt;h3 id=&#34;创建&#34;&gt;创建&lt;/h3&gt;&#xA;&lt;p&gt;最基本的声明方式:(&lt;em&gt;Channel&lt;/em&gt;位于&lt;em&gt;kotlinx.coroutines.channels.Channel&lt;/em&gt;)&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rust中的切片</title>
      <link>https://rivermao.com/program/rust-slice/</link>
      <pubDate>Tue, 31 May 2022 20:59:22 +0800</pubDate>
      <guid>https://rivermao.com/program/rust-slice/</guid>
      <description>&lt;h1 id=&#34;切片slice&#34;&gt;切片(Slice)&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Rust的另一种不持有所有权的数据类型: &lt;strong&gt;切片(slice)&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;一道题,编写一个函数:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;它接收字符串作为参数&lt;/li&gt;&#xA;&lt;li&gt;返回它在这个字符串的第一个空格的索引&lt;/li&gt;&#xA;&lt;li&gt;如果函数没有找到任何空格,那么返回整个字符串的长度&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main(){&#xA;    let s = String::from(&amp;quot;see you&amp;quot;);&#xA;    println!(&amp;quot;{}&amp;quot;,first_word(&amp;amp;s));&#xA;}&#xA;fn first_word(s:&amp;amp;String) -&amp;gt; usize{&#xA;    let my_bytes = s.as_bytes();&#xA;    for (i, &amp;amp;item) in my_bytes.iter().enumerate() {&#xA;        if item == b&#39; &#39;{&#xA;            return i;&#xA;        }&#xA;    }&#xA;    s.len()&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://z3.ax1x.com/2021/08/21/fxYB9O.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rust特性(1)--所有权,深浅拷贝,引用,借用,悬空引用(野指针)</title>
      <link>https://rivermao.com/program/rust-features-01/</link>
      <pubDate>Tue, 31 May 2022 20:59:22 +0800</pubDate>
      <guid>https://rivermao.com/program/rust-features-01/</guid>
      <description>&lt;h2 id=&#34;内存模型&#34;&gt;内存模型&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Rust的内存可分为**栈(stack)&lt;strong&gt;和&lt;/strong&gt;堆(heap)**两种&lt;/li&gt;&#xA;&lt;li&gt;标量会被分配在栈上&lt;/li&gt;&#xA;&lt;li&gt;栈为后进先出&lt;/li&gt;&#xA;&lt;li&gt;分配在堆上的变量在使用时要注意一个叫做&lt;strong&gt;所有权&lt;/strong&gt;的概念&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;所有权ownership&#34;&gt;所有权(Ownership)&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;变量的所有权与变量的声明作用域相同,在变量离开作用域时,变量会发生Drop操作,除非发生所有权的&lt;strong&gt;移交(move)&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;深拷贝deep-copy与浅拷贝shallow-copy&#34;&gt;深拷贝(deep copy)与浅拷贝(shallow copy)&lt;/h2&gt;&#xA;&lt;h3 id=&#34;堆上数据的拷贝&#34;&gt;堆上数据的拷贝:&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;分配在堆上的变量默认使用的是浅拷贝&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rust的函数</title>
      <link>https://rivermao.com/program/rust-function/</link>
      <pubDate>Tue, 31 May 2022 20:59:22 +0800</pubDate>
      <guid>https://rivermao.com/program/rust-function/</guid>
      <description>&lt;h1 id=&#34;函数&#34;&gt;函数&lt;/h1&gt;&#xA;&lt;h2 id=&#34;函数的声明&#34;&gt;函数的声明&lt;/h2&gt;&#xA;&lt;pre&gt;&lt;code class=&#34;language-rust&#34;&gt;fn main() {&#xA;    println!(&amp;quot;This&amp;quot;);&#xA;    another_function();&#xA;}&#xA;&#xA;fn another_function(){&#xA;    println!(&amp;quot;Another&amp;quot;)&#xA;}&#xA;&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;函数不必定义在main前,声明在在其后依然可以在main中调用&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;函数的参数&#34;&gt;函数的参数&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;形参&lt;/strong&gt; parameters&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;实参&lt;/strong&gt; arguments&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;在函数的声明里,必须声明每个参数的类型:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rust的变量、常量与遮蔽(Shadowing)</title>
      <link>https://rivermao.com/program/rust-variable-constants-shadowing/</link>
      <pubDate>Tue, 31 May 2022 20:59:22 +0800</pubDate>
      <guid>https://rivermao.com/program/rust-variable-constants-shadowing/</guid>
      <description>&lt;h1 id=&#34;rust的变量常量shadowing&#34;&gt;Rust的变量,常量,Shadowing&lt;/h1&gt;&#xA;&lt;h2 id=&#34;变量&#34;&gt;变量&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;声明变量使用let关键字&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;默认情况下,Rust的变量是不可变的(immediate),但这与常量仍有很大的区别&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;在声明变量时,如果变量名前加上_mut_关键字,就可以使此变量可变&lt;/p&gt;</description>
    </item>
    <item>
      <title>Rust的数据类型</title>
      <link>https://rivermao.com/program/rust-data_type/</link>
      <pubDate>Tue, 31 May 2022 20:59:22 +0800</pubDate>
      <guid>https://rivermao.com/program/rust-data_type/</guid>
      <description>&lt;h1 id=&#34;rust数据类型&#34;&gt;Rust数据类型&lt;/h1&gt;&#xA;&lt;h2 id=&#34;标量和复合类型&#34;&gt;标量和复合类型&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Rust是静态编译语言,在编译时必须知道所有变量的类型&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;基于使用的值编译器通常能够推断出变量的具体类型&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;但如果可能的类型比较多,就必须标注变量的具体类型,否则在编译期就会报错,例:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Jetbrains系IDE快捷键对照</title>
      <link>https://rivermao.com/program/idea-keymap/</link>
      <pubDate>Tue, 31 May 2022 10:38:55 +0800</pubDate>
      <guid>https://rivermao.com/program/idea-keymap/</guid>
      <description>&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + F&lt;/td&gt;&#xA;          &lt;td&gt;Command + F&lt;/td&gt;&#xA;          &lt;td&gt;在当前文件进行文本查找&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + R&lt;/td&gt;&#xA;          &lt;td&gt;Command + R&lt;/td&gt;&#xA;          &lt;td&gt;在当前文件进行文本替换&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Z&lt;/td&gt;&#xA;          &lt;td&gt;Command + Z&lt;/td&gt;&#xA;          &lt;td&gt;撤销&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Y&lt;/td&gt;&#xA;          &lt;td&gt;Command + Delete&lt;/td&gt;&#xA;          &lt;td&gt;删除光标所在行 或 删除选中的行&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + D&lt;/td&gt;&#xA;          &lt;td&gt;Command + D&lt;/td&gt;&#xA;          &lt;td&gt;复制光标所在行 或 复制选择内容，并把复制内容插入光标位置下面&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + H&lt;/td&gt;&#xA;          &lt;td&gt;Command + D&lt;/td&gt;&#xA;          &lt;td&gt;显示当前类继承关系图&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + W&lt;/td&gt;&#xA;          &lt;td&gt;Option + 方向键上&lt;/td&gt;&#xA;          &lt;td&gt;递进式选择代码块。可选中光标所在的单词或段落，连续按会在原有选中的基础上再扩展选中范围&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + E&lt;/td&gt;&#xA;          &lt;td&gt;Command + E&lt;/td&gt;&#xA;          &lt;td&gt;显示最近打开的文件记录列表&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + N&lt;/td&gt;&#xA;          &lt;td&gt;Command + O&lt;/td&gt;&#xA;          &lt;td&gt;根据输入的类名查找类文件&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + J&lt;/td&gt;&#xA;          &lt;td&gt;Command + J&lt;/td&gt;&#xA;          &lt;td&gt;插入自定义动态代码模板&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + P&lt;/td&gt;&#xA;          &lt;td&gt;Command + P&lt;/td&gt;&#xA;          &lt;td&gt;方法参数提示显示&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + U&lt;/td&gt;&#xA;          &lt;td&gt;Command + U&lt;/td&gt;&#xA;          &lt;td&gt;前往当前光标所在的方法的父类的方法 / 接口定义&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + B&lt;/td&gt;&#xA;          &lt;td&gt;Command + B&lt;/td&gt;&#xA;          &lt;td&gt;进入光标所在的方法/变量的接口或是定义处，等效于Ctrl + 左键单击&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + /&lt;/td&gt;&#xA;          &lt;td&gt;Command + /&lt;/td&gt;&#xA;          &lt;td&gt;注释光标所在行代码，会根据当前不同文件类型使用不同的注释符号&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + F1&lt;/td&gt;&#xA;          &lt;td&gt;Command + F1&lt;/td&gt;&#xA;          &lt;td&gt;在光标所在的错误代码处显示错误信息&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + F11&lt;/td&gt;&#xA;          &lt;td&gt;Option + F3&lt;/td&gt;&#xA;          &lt;td&gt;选中文件 / 文件夹，使用助记符设定 / 取消书签&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Space&lt;/td&gt;&#xA;          &lt;td&gt;Control + Space&lt;/td&gt;&#xA;          &lt;td&gt;基础代码补全，默认在 Windows 系统上被输入法占用，需要进行修改，建议修改为Ctrl + 逗号&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Delete&lt;/td&gt;&#xA;          &lt;td&gt;Option + Fn + Delete&lt;/td&gt;&#xA;          &lt;td&gt;删除光标后面的单词或是中文句&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + BackSpace&lt;/td&gt;&#xA;          &lt;td&gt;Option + Delete&lt;/td&gt;&#xA;          &lt;td&gt;删除光标前面的单词或是中文句&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;Control + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;定位到对应数值的书签位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 加号&lt;/td&gt;&#xA;          &lt;td&gt;Command + 加号&lt;/td&gt;&#xA;          &lt;td&gt;展开代码&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 减号&lt;/td&gt;&#xA;          &lt;td&gt;Command + 减号&lt;/td&gt;&#xA;          &lt;td&gt;折叠代码&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;Control + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;在打开的文件标题上，弹出该文件路径&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;光标跳转到当前单词 / 中文句的左侧开头位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;光标跳转到当前单词 / 中文句的右侧开头位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;预设中没有该快捷键&lt;/td&gt;&#xA;          &lt;td&gt;等效于鼠标滚轮向前效果&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;预设中没有该快捷键&lt;/td&gt;&#xA;          &lt;td&gt;等效于鼠标滚轮向后效果&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + `&lt;/td&gt;&#xA;          &lt;td&gt;Control + V&lt;/td&gt;&#xA;          &lt;td&gt;显示版本控制常用操作菜单弹出层&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + F1&lt;/td&gt;&#xA;          &lt;td&gt;Option + F1&lt;/td&gt;&#xA;          &lt;td&gt;显示当前文件选择目标弹出层，弹出层中有很多目标可以进行选择&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + F7&lt;/td&gt;&#xA;          &lt;td&gt;Option + F7&lt;/td&gt;&#xA;          &lt;td&gt;查询所选对象/变量被引用&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Enter&lt;/td&gt;&#xA;          &lt;td&gt;Option + Enter&lt;/td&gt;&#xA;          &lt;td&gt;IntelliJ IDEA 根据光标所在问题，提供快速修复选择，光标放在的位置不同提示的结果也不同&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Insert&lt;/td&gt;&#xA;          &lt;td&gt;Command + N&lt;/td&gt;&#xA;          &lt;td&gt;代码自动生成，如生成对象的 set / get 方法，构造函数，toString() 等&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;Control + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;切换当前已打开的窗口中的子视图，比如Debug窗口中有Output、Debugger等子视图，用此快捷键就可以在子视图中切换&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;Control + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;切换当前已打开的窗口中的子视图，比如Debug窗口中有Output、Debugger等子视图，用此快捷键就可以在子视图中切换&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;Control + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;当前光标跳转到当前文件的前一个方法名位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;Control + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;当前光标跳转到当前文件的后一个方法名位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;Command + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;显示对应数值的选项卡，其中 1 是 Project 用得最多&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Shift + F11&lt;/td&gt;&#xA;          &lt;td&gt;Command + F3&lt;/td&gt;&#xA;          &lt;td&gt;弹出书签显示层&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Shift + Tab&lt;/td&gt;&#xA;          &lt;td&gt;Shift + Tab&lt;/td&gt;&#xA;          &lt;td&gt;取消缩进&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Shift + Enter&lt;/td&gt;&#xA;          &lt;td&gt;Shift + Enter&lt;/td&gt;&#xA;          &lt;td&gt;开始新一行。光标所在行下空出一行，光标定位到新行位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Shift + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;Shift + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;在打开的文件名上按此快捷键，可以关闭当前打开文件&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + L&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + L&lt;/td&gt;&#xA;          &lt;td&gt;格式化代码，可以对当前文件和整个包目录使用&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + O&lt;/td&gt;&#xA;          &lt;td&gt;Control + Option + O&lt;/td&gt;&#xA;          &lt;td&gt;优化导入的类，可以对当前文件和整个包目录使用&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + T&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + T&lt;/td&gt;&#xA;          &lt;td&gt;对选中的代码弹出环绕选项弹出层&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + S&lt;/td&gt;&#xA;          &lt;td&gt;Command + 逗号&lt;/td&gt;&#xA;          &lt;td&gt;打开 IntelliJ IDEA 系统设置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + Enter&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + Enter&lt;/td&gt;&#xA;          &lt;td&gt;光标所在行上空出一行，光标定位到新行&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;退回到上一个操作的地方&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Alt + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;前进到上一个操作的地方&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + F&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + F&lt;/td&gt;&#xA;          &lt;td&gt;根据输入内容查找整个项目 或 指定目录内文件&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + R&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + F&lt;/td&gt;&#xA;          &lt;td&gt;根据输入内容替换对应内容，范围为整个项目 或 指定目录内文件&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + J&lt;/td&gt;&#xA;          &lt;td&gt;Control + Shift + J&lt;/td&gt;&#xA;          &lt;td&gt;自动将下一行合并到当前行末尾&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Z&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + Z&lt;/td&gt;&#xA;          &lt;td&gt;取消撤销&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + W&lt;/td&gt;&#xA;          &lt;td&gt;Option + 方向键下&lt;/td&gt;&#xA;          &lt;td&gt;递进式取消选择代码块。可选中光标所在的单词或段落，连续按会在原有选中的基础上再扩展取消选中范围&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + N&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + O&lt;/td&gt;&#xA;          &lt;td&gt;通过文件名定位 / 打开文件 / 目录，打开目录需要在输入的内容后面多加一个正斜杠&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + U&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + U&lt;/td&gt;&#xA;          &lt;td&gt;对选中的代码进行大 / 小写轮流转换&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + T&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + T&lt;/td&gt;&#xA;          &lt;td&gt;对当前类生成单元测试类，如果已经存在的单元测试类则可以进行选择&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + C&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + C&lt;/td&gt;&#xA;          &lt;td&gt;复制当前文件磁盘路径到剪贴板&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + B&lt;/td&gt;&#xA;          &lt;td&gt;Control + Shift + B&lt;/td&gt;&#xA;          &lt;td&gt;跳转到类型声明处&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + /&lt;/td&gt;&#xA;          &lt;td&gt;Command + Option + /&lt;/td&gt;&#xA;          &lt;td&gt;代码块注释&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + [&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + [&lt;/td&gt;&#xA;          &lt;td&gt;选中从光标所在位置到它的顶部中括号位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + ]&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + ]&lt;/td&gt;&#xA;          &lt;td&gt;选中从光标所在位置到它的底部中括号位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 加号&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + 加号&lt;/td&gt;&#xA;          &lt;td&gt;展开所有代码&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 减号&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + 减号&lt;/td&gt;&#xA;          &lt;td&gt;折叠所有代码&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + F7&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + F7&lt;/td&gt;&#xA;          &lt;td&gt;高亮显示所有该选中文本，按Esc高亮消失&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + F12&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + F12&lt;/td&gt;&#xA;          &lt;td&gt;编辑器最大化&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Enter&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + Enter&lt;/td&gt;&#xA;          &lt;td&gt;自动结束代码，行末自动添加分号&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Backspace&lt;/td&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Backspace&lt;/td&gt;&#xA;          &lt;td&gt;退回到上次修改的地方&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;Control + Shift + 1,2,3&amp;hellip;9&lt;/td&gt;&#xA;          &lt;td&gt;快速添加指定数值的书签&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + 左键单击&lt;/td&gt;&#xA;          &lt;td&gt;把光标放在某个类变量上，按此快捷键可以直接定位到该类中&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + 左方向键&lt;/td&gt;&#xA;          &lt;td&gt;在代码文件上，光标跳转到当前单词 / 中文句的左侧开头位置，同时选中该单词 / 中文句&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + 右方向键&lt;/td&gt;&#xA;          &lt;td&gt;在代码文件上，光标跳转到当前单词 / 中文句的右侧开头位置，同时选中该单词 / 中文句&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;光标放在方法名上，将方法移动到上一个方法前面，调整方法排序&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;光标放在方法名上，将方法移动到下一个方法前面，调整方法排序&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Shift + N&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + B&lt;/td&gt;&#xA;          &lt;td&gt;选择 / 添加 task&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Shift + 左键双击&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + 左键双击&lt;/td&gt;&#xA;          &lt;td&gt;选择被双击的单词 / 中文句，按住不放，可以同时选择其他单词 / 中文句&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Shift + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + 前方向键&lt;/td&gt;&#xA;          &lt;td&gt;移动光标所在行向上移动&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Alt + Shift + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;Option + Shift + 后方向键&lt;/td&gt;&#xA;          &lt;td&gt;移动光标所在行向下移动&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/th&gt;&#xA;          &lt;th&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Alt + V&lt;/td&gt;&#xA;          &lt;td&gt;Command + Shift + Option + V&lt;/td&gt;&#xA;          &lt;td&gt;无格式黏贴&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Ctrl + Shift + Alt + S&lt;/td&gt;&#xA;          &lt;td&gt;Command + ;&lt;/td&gt;&#xA;          &lt;td&gt;打开当前项目设置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Win 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Mac 快捷键&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;strong&gt;介绍&lt;/strong&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;F2&lt;/td&gt;&#xA;          &lt;td&gt;F2&lt;/td&gt;&#xA;          &lt;td&gt;跳转到下一个高亮错误 或 警告位置&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;F4&lt;/td&gt;&#xA;          &lt;td&gt;F4&lt;/td&gt;&#xA;          &lt;td&gt;编辑源&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;F11&lt;/td&gt;&#xA;          &lt;td&gt;F3&lt;/td&gt;&#xA;          &lt;td&gt;添加书签&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;F12&lt;/td&gt;&#xA;          &lt;td&gt;F12&lt;/td&gt;&#xA;          &lt;td&gt;回到前一个工具窗口&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Tab&lt;/td&gt;&#xA;          &lt;td&gt;Tab&lt;/td&gt;&#xA;          &lt;td&gt;缩进&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;ESC&lt;/td&gt;&#xA;          &lt;td&gt;ESC&lt;/td&gt;&#xA;          &lt;td&gt;从工具窗口进入代码文件窗口&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;</description>
    </item>
    <item>
      <title>About Me</title>
      <link>https://rivermao.com/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://rivermao.com/about/</guid>
      <description>&lt;ul&gt;&#xA;&lt;li&gt;CS major, currently working in software development, based in Nanjing.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/vaspike&#34;&gt;Github Homepage&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;del&gt;Java,Kotlin,JavaScript,Go,Python,C,C++ ,Rust, Swift;&lt;/del&gt;   | &lt;strong&gt;AI;&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;My Product: &lt;a href=&#34;https://rivermao.com/dev/devswitcher2&#34;&gt;DevSwitcher2&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Email: &lt;a href=&#34;mailto:rivermao@outlook.com&#34;&gt;rivermao@outlook.com&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;hr&gt;&#xA;&lt;div class=&#34;solana-tip-container&#34;&gt;&#xA;  &lt;div class=&#34;solana-header&#34;&gt;&#xA;    &lt;h3 class=&#34;solana-title&#34;&gt;Sponsor&lt;/h3&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;wallet-section&#34;&gt;&#xA;  &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;149&#34; height=&#34;22&#34; fill=&#34;none&#34; style=&#34;color:var(--body-text)&#34;&gt;&lt;mask id=&#34;kw92m5ht&#34; width=&#34;149&#34; height=&#34;23&#34; x=&#34;0&#34; y=&#34;0&#34; maskUnits=&#34;userSpaceOnUse&#34; style=&#34;mask-type:luminance&#34;&gt;&lt;path fill=&#34;#fff&#34; d=&#34;M0 0h149v22.142H0z&#34;&gt;&lt;/path&gt;&lt;/mask&gt;&lt;g mask=&#34;url(#kw92m5ht)&#34;&gt;&lt;path fill=&#34;url(#pn47x3vj)&#34; d=&#34;m25.033 17.458-4.087 4.382a.95.95 0 0 1-.692.302H.879a.476.476 0 0 1-.348-.798l4.082-4.382a.95.95 0 0 1 .692-.302H24.68a.473.473 0 0 1 .353.798m-4.087-8.827a.96.96 0 0 0-.692-.302H.879a.475.475 0 0 0-.348.798l4.082 4.385a.96.96 0 0 0 .692.302H24.68a.476.476 0 0 0 .346-.798zM.879 5.483h19.375a.95.95 0 0 0 .692-.302L25.033.798a.475.475 0 0 0-.09-.724A.47.47 0 0 0 24.68 0H5.305a.95.95 0 0 0-.692.302L.531 4.685a.475.475 0 0 0 .348.798&#34;&gt;&lt;/path&gt;&lt;path fill=&#34;currentColor&#34; d=&#34;M48.653 9.365H38.288V5.95h13.06V2.538H38.252a3.407 3.407 0 0 0-3.425 3.388v3.46a3.406 3.406 0 0 0 3.425 3.392h10.38v3.414H35.075v3.413h13.578a3.41 3.41 0 0 0 3.425-3.388v-3.46a3.406 3.406 0 0 0-3.425-3.392m20.08-6.827H58.33a3.407 3.407 0 0 0-3.434 3.388v10.291a3.405 3.405 0 0 0 3.434 3.389h10.405a3.407 3.407 0 0 0 3.425-3.389V5.926a3.4 3.4 0 0 0-2.12-3.136 3.4 3.4 0 0 0-1.305-.252Zm-.025 13.654H58.354V5.952h10.35zm36.468-13.654H95.028a3.407 3.407 0 0 0-3.425 3.388v13.68h3.46v-5.607h10.102v5.607h3.46V5.926a3.41 3.41 0 0 0-2.136-3.143 3.4 3.4 0 0 0-1.313-.246Zm-.025 8.047H95.049V5.951h10.102zm40.424-8.047h-10.149a3.406 3.406 0 0 0-3.425 3.388v13.68h3.46v-5.607h10.079v5.607H149V5.926a3.42 3.42 0 0 0-1.011-2.403 3.4 3.4 0 0 0-2.414-.985m-.035 8.047h-10.102V5.951h10.102zm-20.066 5.607h-1.384l-4.948-12.224a2.27 2.27 0 0 0-2.113-1.43h-3.07a2.27 2.27 0 0 0-2.283 2.26v14.808h3.46V5.95h1.384l4.945 12.225a2.285 2.285 0 0 0 2.122 1.42h3.07a2.27 2.27 0 0 0 2.283-2.26V2.538h-3.466zm-46.8-13.654h-3.46v13.68a3.405 3.405 0 0 0 3.438 3.388H89.03v-3.414H78.675z&#34;&gt;&lt;/path&gt;&lt;/g&gt;&lt;defs&gt;&lt;linearGradient id=&#34;pn47x3vj&#34; x1=&#34;2.494&#34; x2=&#34;22.809&#34; y1=&#34;22.671&#34; y2=&#34;-0.233&#34; gradientUnits=&#34;userSpaceOnUse&#34;&gt;&lt;stop offset=&#34;0.08&#34; stop-color=&#34;#9945FF&#34;&gt;&lt;/stop&gt;&lt;stop offset=&#34;0.3&#34; stop-color=&#34;#8752F3&#34;&gt;&lt;/stop&gt;&lt;stop offset=&#34;0.5&#34; stop-color=&#34;#5497D5&#34;&gt;&lt;/stop&gt;&lt;stop offset=&#34;0.6&#34; stop-color=&#34;#43B4CA&#34;&gt;&lt;/stop&gt;&lt;stop offset=&#34;0.72&#34; stop-color=&#34;#28E0B9&#34;&gt;&lt;/stop&gt;&lt;stop offset=&#34;0.97&#34; stop-color=&#34;#19FB9B&#34;&gt;&lt;/stop&gt;&lt;/linearGradient&gt;&lt;/defs&gt;&lt;/svg&gt;&#xA;    &lt;label class=&#34;wallet-label&#34;&gt;Solana&lt;/label&gt;&#xA;    &lt;div class=&#34;wallet-address&#34;&gt;&#xA;      &lt;span class=&#34;wallet-text&#34; id=&#34;walletAddress&#34;&gt;GjKB96Tu2vb2trtUyDxM1JZqsz5d5oQvN7xHdRotqme3&lt;/span&gt;&#xA;      &lt;button class=&#34;copy-btn&#34; onclick=&#34;copyWalletAddress()&#34; id=&#34;copyBtn&#34;&gt;Copy&lt;/button&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;  &lt;div class=&#34;qr-section&#34;&gt;&#xA;    &lt;div class=&#34;qr-header&#34;&gt;&#xA;      &lt;span class=&#34;qr-icon&#34;&gt;📱&lt;/span&gt;&#xA;      &lt;span&gt;Scan &amp; Send&lt;/span&gt;&#xA;      &lt;span class=&#34;qr-icon&#34;&gt;⚡&lt;/span&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;qr-code&#34;&gt;&#xA;      &lt;div class=&#34;qr-decorations&#34;&gt;&#xA;      &lt;/div&gt;&#xA;      &lt;img src=&#34;https://api.qrserver.com/v1/create-qr-code/?size=160x160&amp;data=GjKB96Tu2vb2trtUyDxM1JZqsz5d5oQvN7xHdRotqme3&#34; alt=&#34;Solana钱包二维码&#34; /&gt;&#xA;    &lt;/div&gt;&#xA;  &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&lt;script&gt;&#xA;// 复制钱包地址功能&#xA;function copyWalletAddress() {&#xA;  const walletAddress = document.getElementById(&#39;walletAddress&#39;).textContent;&#xA;  const copyBtn = document.getElementById(&#39;copyBtn&#39;);&#xA;  &#xA;  navigator.clipboard.writeText(walletAddress).then(function() {&#xA;    copyBtn.textContent = &#39;Copied!&#39;;&#xA;    copyBtn.style.background = &#39;linear-gradient(45deg, #14f195, #9945ff)&#39;;&#xA;    &#xA;    setTimeout(function() {&#xA;      copyBtn.textContent = &#39;Copy&#39;;&#xA;      copyBtn.style.background = &#39;linear-gradient(45deg, #9945ff, #14f195)&#39;;&#xA;    }, 2000);&#xA;  }).catch(function(err) {&#xA;    console.error(&#39;复制失败: &#39;, err);&#xA;    // 兼容性处理&#xA;    const textArea = document.createElement(&#39;textarea&#39;);&#xA;    textArea.value = walletAddress;&#xA;    document.body.appendChild(textArea);&#xA;    textArea.select();&#xA;    document.execCommand(&#39;copy&#39;);&#xA;    document.body.removeChild(textArea);&#xA;    &#xA;    copyBtn.textContent = &#39;已复制!&#39;;&#xA;    setTimeout(function() {&#xA;      copyBtn.textContent = &#39;复制&#39;;&#xA;    }, 2000);&#xA;  });&#xA;}&#xA;&#xA;&#xA;// 添加一些交互动画&#xA;document.addEventListener(&#39;DOMContentLoaded&#39;, function() {&#xA;  const container = document.querySelector(&#39;.solana-tip-container&#39;);&#xA;  if (container) {&#xA;    // 添加鼠标进入效果&#xA;    container.addEventListener(&#39;mouseenter&#39;, function() {&#xA;      this.style.background = &#39;linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 50%, #cbd5e1 100%)&#39;;&#xA;    });&#xA;    &#xA;    container.addEventListener(&#39;mouseleave&#39;, function() {&#xA;      this.style.background = &#39;linear-gradient(135deg, #f8fafc 0%, #e2e8f0 50%, #cbd5e1 100%)&#39;;&#xA;    });&#xA;  }&#xA;});&#xA;&lt;/script&gt;</description>
    </item>
  </channel>
</rss>
