Java字符串入门:API入门+String类核心

🏠个人主页:黎雁
🎬作者简介:C/C++/JAVA后端开发学习者
❄️个人专栏:C语言、数据结构(C语言)、EasyX、JAVA、游戏、规划、程序人生
✨ 从来绝巘须孤往,万里同尘即玉京

文章目录

  • ✨Java字符串入门:API入门+String类核心|从底层原理到实战用法 吃透字符串基础 ✅
    • 📌 文章摘要
      • 🕒 阅读时长:约18分钟
      • ✅ 适用人群 & 阅读重点
    • 📖 知识回顾(入门铺垫)
    • 一、API基础认知 📚 解锁Java预定义工具的正确姿势
      • 1.1 什么是API?(入门必懂)
      • 1.2 API帮助文档:Java开发者的字典 📖
        • ✔ API帮助文档使用步骤(标准化流程)
    • 二、String类核心精讲 🔥 字符串的本质与核心用法
      • 2.1 String类概述(必背核心)
        • 示例:理解字符串不可变特性
      • 2.2 创建String对象的两种核心方式(笔试高频)
        • ✔ 方式一:直接赋值(推荐,复用串池对象)
        • ✔ 方式二:通过`new`关键字调用构造方法
        • 完整示例代码:
      • 2.3 String内存分析:串池(StringTable)核心逻辑
        • 场景1:直接赋值的内存逻辑
        • 场景2:new创建的内存逻辑(以字符数组为例)
      • 2.4 字符串比较:== vs equals(面试必考)
        • 第一步:明确数据类型的比较规则
        • 第二步:String类的比较方法(比较内容)
        • 示例代码:
      • 2.5 String类高频实用方法(开发必备)
        • 方法1:charAt(int index) → 根据索引获取字符
        • 方法2:length() → 获取字符串长度
        • 示例:遍历字符串的每个字符
        • 方法3:substring() → 截取字符串(两个重载)
        • 示例:手机号脱敏(中间4位替换为****)
        • 方法4:replace() → 替换字符串内容
        • 示例:敏感词替换
    • 三、核心考点提炼 📝 笔试/面试必记
      • ✅ 核心考点1:String的不可变特性
      • ✅ 核心考点2:串池(StringTable)规则
      • ✅ 核心考点3:比较规则
      • ✅ 核心考点4:常用方法易错点
      • ✅ 经典面试题解析
        • 面试题1:
        • 面试题2:
    • ✍️ 写在最后
    • 💡 下期预告

✨Java字符串入门:API入门+String类核心|从底层原理到实战用法 吃透字符串基础 ✅

📌 文章摘要

本文是Java字符串系列第一篇核心内容,从API基础概念切入,系统讲解String类的核心知识点:包括String类的本质特性、多种创建方式、内存存储逻辑(串池)、字符串比较规则及高频实用方法(charAt、length、截取、替换)。全文结合底层原理分析+实战代码示例,拆解字符串“不可变”特性、串池复用机制、==equals的核心区别等易混淆点,内容由浅入深、考点明确、注释详尽。零基础可快速掌握String类基础用法,在校生能吃透笔试高频考点,入门者可夯实字符串底层认知,是攻克Java字符串基础的必备篇章。

🕒 阅读时长:约18分钟

✅ 适用人群 & 阅读重点

▫️Java零基础入门者:重点看String类创建方式、常用方法的代码示例与注释,跟着敲写代码,掌握字符串基础操作。
▫️在校学生/笔试备考者:吃透字符串内存分析(串池)、==equals区别、编译期优化等面试/笔试高频考点
▫️开发入门夯实基础者:聚焦String类“不可变”特性的底层逻辑,理解为何拼接字符串建议用StringBuilder。
▫️字符串基础薄弱者:重点看知识点拆解与示例,理清“直接赋值”与“new创建”的内存差异,打通基础认知闭环。
▫️复习巩固者:直接看「核心考点提炼+面试题解析」,快速梳理String类核心考点,查漏补缺。

📖 知识回顾(入门铺垫)

在Java基础语法学习阶段,我们已经接触过字符串的简单使用(如直接赋值String s = "abc"),但并未深入理解其底层原理与核心特性。字符串是Java开发中使用频率最高的数据类型之一,从控制台输入输出、业务数据处理到接口参数传递,几乎所有场景都离不开字符串操作。

而要真正掌握字符串,首先要理解Java提供的字符串相关API(Application Programming Interface)——这些是JDK预定义的工具类,能帮我们高效实现字符串的创建、比较、截取、替换等操作。本篇作为字符串系列开篇,先从API基础概念入手,再深入剖析核心的String类,为后续学习StringBuilderStringJoiner打下坚实基础。

一、API基础认知 📚 解锁Java预定义工具的正确姿势

1.1 什么是API?(入门必懂)

💡API(Application Programming Interface):中文译为“应用程序编程接口”,可以简单理解为:别人已经写好的、可直接调用的功能代码

你无需关心这些代码的底层实现细节(比如字符串如何存储、比较逻辑如何编写),只需要学习“如何调用”就能实现对应的功能。比如要比较两个字符串的内容,直接调用equals()方法即可,不用自己写循环对比每个字符。

Java API:特指JDK中提供的所有Java类(如StringScannerArrayList等),这些类封装了底层实现,我们只需调用其方法/属性,就能快速实现各种功能,是Java开发的核心工具库。

1.2 API帮助文档:Java开发者的字典 📖

API帮助文档是查询、学习Java API的官方工具(常用版本如JDK_API_1_6_zh_CN.CHM),能帮我们快速找到类的包路径、构造方法、成员方法及使用说明。

⚠️ 小提示:中文帮助文档多为机器翻译,部分术语可能不够精准,但不影响核心用法理解。

✔ API帮助文档使用步骤(标准化流程)
  1. 打开文档 → 点击「显示」→ 选择「索引」;
  2. 在输入框中输入要查询的类名(如String)→ 点击「显示」;
  3. 查看类的包路径(如Stringjava.lang包下,无需导包)和类的描述(核心特性);
  4. 查看类的构造方法(如何创建对象)和成员方法(可调用的功能)。

核心技巧:重点关注方法的「参数类型」「返回值类型」「方法说明」,这是正确调用的关键。

二、String类核心精讲 🔥 字符串的本质与核心用法

2.1 String类概述(必背核心)

  • java.lang.String类代表字符串,Java程序中所有双引号包裹的字符串文字(如"abc""得鹿梦鱼")都是String类的对象;
  • java.lang是Java核心包,使用该包下的类无需手动导包
  • ✨ 最关键特性:字符串的内容一旦创建就不可改变(对象在创建后,字符序列不能被修改)。
示例:理解字符串不可变特性
// 示例1:字符串拼接Stringname="王哥";StringnewName="得鹿梦鱼";System.out.println(name+newName);// 输出:王哥得鹿梦鱼// 说明:name本身还是"王哥",newName还是"得鹿梦鱼",拼接只是生成了新字符串,原字符串未变// 示例2:变量引用变更Stringname="王哥";name="得鹿梦鱼";// 说明:不是"王哥"这个字符串对象变了,而是name变量的引用从"王哥"指向了新的字符串对象"得鹿梦鱼"

核心总结:字符串对象本身不可变,可变的是指向字符串的变量引用。

2.2 创建String对象的两种核心方式(笔试高频)

创建String对象有两种核心方式,对应不同的内存逻辑,是笔试/面试的必考考点:

✔ 方式一:直接赋值(推荐,复用串池对象)

语法:String 变量名 = "字符串内容";
示例:String s1 = "得鹿梦鱼";

✔ 方式二:通过new关键字调用构造方法

String类提供了多个构造方法,常用的如下:

构造方法说明适用场景
public String()创建空白字符串(无任何内容)临时存储空字符串
public String(String original)根据传入的字符串创建新对象复制已有字符串(极少用)
public String(char[] chs)根据字符数组创建字符串需要修改字符串内容时(字符数组可变)
public String(byte[] chs)根据字节数组创建字符串网络传输/文件读取时(字节转字符串)
完整示例代码:
publicclassStringCreateDemo{publicstaticvoidmain(String[]args){// 方式1:直接赋值Strings1="abc";System.out.println(s1);// 输出:abc// 方式2:调用构造方法// 2.1 空参构造:创建空白字符串Strings2=newString();System.out.println("@"+s2+"!");// 输出:@!(中间无内容)// 2.2 传入字符串:创建新的字符串对象Strings3=newString("abc");System.out.println(s3);// 输出:abc// 2.3 传入字符数组:灵活构建字符串(字符数组可变)char[]chs={'a','b','c','d'};Strings4=newString(chs);System.out.println(s4);// 输出:abcd// 2.4 传入字节数组:字节转字符串(网络/文件场景)byte[]bytes={97,98,99,100};// ASCII码:97→a,98→b,99→c,100→dStrings5=newString(bytes);System.out.println(s5);// 输出:abcd}}

2.3 String内存分析:串池(StringTable)核心逻辑

要理解String的内存机制,首先要掌握字符串常量池(StringTable/串池)

  • 串池是JVM为字符串开辟的专门内存区域,用于存储字符串常量;
  • JDK 7及以后,串池从“方法区”迁移到“堆内存”;
  • 核心规则:直接赋值的字符串会存入串池,重复赋值时复用已有对象;new创建的字符串不会复用,每次都新建对象
场景1:直接赋值的内存逻辑
Strings1="abc";Strings2="abc";// 内存过程:// 1. JVM检查串池,发现没有"abc",创建该对象并存入串池;// 2. s1指向串池中的"abc";// 3. 创建s2时,JVM检查串池存在"abc",直接让s2指向该对象(复用);// 4. s1和s2指向同一个对象,地址值相同。
场景2:new创建的内存逻辑(以字符数组为例)
char[]chs={'a','b','c'};Strings1=newString(chs);Strings2=newString(chs);// 内存过程:// 1. 字符数组chs存储在堆内存;// 2. new String(chs)时,会在堆内存新建一个String对象,指向chs的字符序列;// 3. s1和s2是两个不同的对象,地址值不同(即使内容相同);// 4. 这种方式不会复用串池中的对象,会浪费内存。

核心结论:直接赋值的字符串效率更高(复用串池),new创建的字符串会产生冗余对象,非必要不使用。

2.4 字符串比较:== vs equals(面试必考)

字符串比较是高频考点,核心要区分“==”和“equals”的本质区别:

第一步:明确数据类型的比较规则
数据类型比较方式示例结果分析
基本数据类型(int、char等)比较具体的值int a=10; int b=20; System.out.println(a==b);false(值不同)
引用数据类型(String、数组等)比较地址值String s1=new String("abc"); String s2=new String("abc"); System.out.println(s1==s2);false(地址不同)
第二步:String类的比较方法(比较内容)

为了实现“比较字符串内容”的需求,String类提供了两个核心方法:

  1. public boolean equals(Object anObject):严格比较内容(区分大小写),内容完全一致返回true;
  2. public boolean equalsIgnoreCase(String anotherString):忽略大小写比较内容,适合验证码、用户名等场景。
示例代码:
publicclassStringCompareDemo{publicstaticvoidmain(String[]args){Strings1=newString("abc");Strings2="ABC";Strings3="abc";// == 比较:地址值System.out.println(s1==s3);// false(s1是new的,s3在串池)System.out.println(s1==s2);// false(地址+内容都不同)// equals:区分大小写比较内容booleanresult1=s1.equals(s2);System.out.println(result1);// false// equalsIgnoreCase:忽略大小写比较内容booleanresult2=s1.equalsIgnoreCase(s2);System.out.println(result2);// true}}

开发规范:只要想比较字符串的内容,就用equals/equalsIgnoreCase,永远不要用==(键盘录入的字符串也是new出来的,==比较必错)。

2.5 String类高频实用方法(开发必备)

String类提供了大量方法,以下是最常用的核心方法,必须熟练掌握:

方法1:charAt(int index) → 根据索引获取字符
  • 作用:返回字符串中指定索引位置的字符;
  • 注意:字符串索引从0开始,越界会抛出StringIndexOutOfBoundsException
方法2:length() → 获取字符串长度
  • 作用:返回字符串的字符个数;
  • 注意:字符串长度是length()方法,数组长度是length属性(易混淆考点)。
示例:遍历字符串的每个字符
importjava.util.Scanner;publicclassStringCharDemo{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);System.out.println("请输入一个字符串:");Stringstr=sc.next();// 示例输入:得鹿梦鱼// 遍历每个字符for(inti=0;i<str.length();i++){charc=str.charAt(i);System.out.println("索引"+i+"的字符:"+c);}// 输出:// 索引0的字符:得// 索引1的字符:鹿// 索引2的字符:梦// 索引3的字符:鱼}}
方法3:substring() → 截取字符串(两个重载)
  • String substring(int beginIndex):从指定索引截取到字符串末尾;
  • String substring(int beginIndex, int endIndex):从beginIndex截取到endIndex(包前不包后/左闭右开);
  • 核心:返回新字符串,原字符串不变(符合“不可变”特性)。
示例:手机号脱敏(中间4位替换为****)
publicclassStringSubDemo{publicstaticvoidmain(String[]args){Stringphone="18315729850";// 11位手机号// 截取前3位:0~3(包0不包3)Stringprefix=phone.substring(0,3);// 截取后4位:从索引7开始到末尾Stringsuffix=phone.substring(7);// 拼接脱敏结果StringhidePhone=prefix+"****"+suffix;System.out.println(hidePhone);// 输出:183****9850}}
方法4:replace() → 替换字符串内容
  • 方法:String replace(CharSequence target, CharSequence replacement)
  • 作用:将原字符串中的target替换为replacement,返回新字符串;
  • 核心:原字符串不变,替换结果通过返回值接收。
示例:敏感词替换
publicclassStringReplaceDemo{publicstaticvoidmain(String[]args){Stringtalk="abc这个词是敏感词,不能出现在内容中";// 替换敏感词StringnewTalk=talk.replace("abc","***");System.out.println(newTalk);// 输出:***这个词是敏感词,不能出现在内容中}}

拓展:更多方法(如contains()startsWith()split()等)可通过API帮助文档查询,核心是掌握“方法参数、返回值、功能”三个关键点。

三、核心考点提炼 📝 笔试/面试必记

✅ 核心考点1:String的不可变特性

字符串对象创建后内容不可变,变量的“修改”本质是指向新对象,会产生冗余对象(拼接时尤其明显)。

✅ 核心考点2:串池(StringTable)规则

  • 直接赋值:字符串存入串池,重复赋值复用对象(地址相同);
  • new创建:堆内存新建对象,不复用串池(地址不同)。

✅ 核心考点3:比较规则

  • ==:基本类型比数值,引用类型比地址;
  • equals:String类重写后比内容(区分大小写);
  • equalsIgnoreCase:忽略大小写比内容。

✅ 核心考点4:常用方法易错点

  • length()是方法(字符串),length是属性(数组);
  • substring(begin, end)包前不包后,索引从0开始;
  • 所有修改字符串的方法(如replace()substring())都返回新字符串,原字符串不变。

✅ 经典面试题解析

面试题1:
publicclassStringTest1{publicstaticvoidmain(String[]args){Strings1="abc";Strings2="ab";Strings3=s2+"c";System.out.println(s1==s3);// 输出:false}}

解析

  • s2是变量,拼接时会触发运行时创建新对象(而非编译期优化);
  • s1在串池,s3是new出来的对象,地址不同,故==返回false。
面试题2:
publicclassStringTest2{publicstaticvoidmain(String[]args){Strings1="abc";Strings2="a"+"b"+"c";System.out.println(s1==s2);// 输出:true}}

解析

  • 拼接的都是字符串常量,触发编译期优化,直接编译为"abc";
  • s2复用串池中的s1对象,地址相同,故==返回true。

✍️ 写在最后

本篇我们吃透了Java字符串的核心基础——String类的本质、创建方式、内存逻辑、比较规则及常用方法。String类的“不可变”特性是理解后续StringBuilderStringJoiner的关键:正因为String不可变,拼接时会产生大量冗余对象,才需要StringBuilder来优化效率。

字符串是Java开发的基础中的基础,也是笔试/面试的高频考点,尤其是串池、==与equals的区别、编译期优化这些知识点,一定要理解透彻,而非死记硬背。

作为字符串系列的第一篇,我们完成了基础认知的搭建,下一篇将聚焦StringBuilder类,讲解如何解决字符串拼接效率低的问题,同时深入剖析其底层扩容机制,实现从“会用”到“懂原理”的进阶。

Java学习之路,基础不牢,地动山摇。愿你把每个知识点学透,一步一个脚印夯实基础!✨

💡 下期预告

Java字符串精讲(二):StringBuilder类核心|底层扩容原理+高效拼接/反转实战,吃透字符串优化技巧!

本文为Java字符串系列第一篇,案例均经过实测可运行,代码规范贴合企业开发。如果对你有帮助,欢迎点赞+收藏+关注,后续会持续更新Java字符串核心知识点与实战案例!有问题可在评论区留言,逐一回复解答~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据领域 GDPR 合规性评估方法

大数据领域GDPR合规性评估方法&#xff1a;从"踩雷"到"避雷"的系统指南 一、引入&#xff1a;当大数据撞上"史上最严"数据法 2022年&#xff0c;Meta因"剑桥分析门"后续的GDPR违规被欧盟罚款12亿欧元——这不是个例。同年&#xff0c;…

亲测好用9个AI论文软件,MBA论文写作必备!

亲测好用9个AI论文软件&#xff0c;MBA论文写作必备&#xff01; AI 工具助力论文写作&#xff0c;高效与精准并存 在当今学术研究日益数字化的背景下&#xff0c;AI 工具正逐渐成为 MBA 学生和科研工作者不可或缺的助手。无论是撰写论文、优化内容&#xff0c;还是降低 AIGC 率…

MonkeyCode+cpolar,让国产 AI 编程助手随时随地用

目录前言AI助手千千万&#xff0c;找到适合你的才能事半功倍。有需要的朋友教程在下面请自取呦&#xff01;1.MonkeyCode安装条件2.在linux安装MonkeyCode3.在VS Code中使用4.安装cpolar实现随时随地开发5.配置公网地址6.保留固定公网地址总结前言 MonkeyCode 作为国产开源的 …

强烈安利10个AI论文网站,继续教育学生轻松搞定论文写作!

强烈安利10个AI论文网站&#xff0c;继续教育学生轻松搞定论文写作&#xff01; AI 工具&#xff0c;让论文写作不再难 在当前的学术环境中&#xff0c;继续教育学生面临着越来越高的论文写作要求。无论是学位论文、研究报告&#xff0c;还是课程作业&#xff0c;都需要高质量的…

【Yolactedge】Unbuntu22.04运行Yolactedge推理

主要用于自己搭建环境&#xff0c;有不对的地方欢迎讨论。 文章目录前言一、环境构建1.1 CUDA11.8安装1.2 虚拟环境构建1.3 pytorch安装1.4 其它依赖二、评估推理2.1 权重下载文件2.2 推理前言 Yolactedge地址&#xff1a;Yolactedge 采用CUDA11.8torch2.0.1 一、环境构建 下…

STM32 标准外设库中关于 GPIO(通用输入输出) 模块的函数声明

这些函数通常位于 stm32f10x_gpio.h 文件中&#xff0c;为了方便你理解&#xff0c;我将这些函数按照功能逻辑进行了分类解析&#xff1a; 目录 1.初始化与配置函数 2.读取输入信号函数 3.读取输出状态函数 4.控制输出电平函数 5.高级/特殊功能函数 1.GPIO_Init(最基础:…

数据分类预测总让人头秃,传统BP神经网络容易掉进局部最优解的大坑。今天咱们搞点刺激的——用遗传算法给BP神经网络调参,直接在MATLAB里整活

基于遗传算法优化BP神经网络&#xff08;GA-BP&#xff09;的数据分类预测 matlab代码先看核心套路&#xff1a;遗传算法负责全局搜索找最优初始权值阈值&#xff0c;BP神经网络拿着这些参数做精细训练。这就像先用无人机扫描整座山找矿脉&#xff0c;再派专业挖矿队定点开挖。…

SSAS - 生成模拟测试数据

在分析系统中&#xff0c;因为数据量太大&#xff0c;无法直观看出统计结果的正确性。在使用新技术时&#xff0c;需要使用简单的数据&#xff0c;来验证语句的结果。本文介绍SQL Server生成模拟数据的方法。 使用技术 一、静态数据&#xff1a;VALUES 使用说明 格式&#xff1…

基于FPGA的图像形态学腐蚀处理Verilog开发与开发板硬件测试

目录 1.前言 2.算法硬件测试效果图预览 3.算法运行软件版本 4.部分核心程序 5.算法测试参数 6.硬件测试说明 7.算法理论概述 8.算法完整程序工程 1.前言 本课题为之前博客中写的文章的硬件调试&#xff1a; 基于FPGA的图像形态学腐蚀算法实现,包括tb测试文件和MATLAB…

【技术分享】让AI变“听话“:AI Agent Skill完全指南,收藏备用

文章介绍AI Agent Skill工具&#xff0c;通过结构化知识文档解决AI自作主张、质量不稳定和重复劳动三大痛点。Skill包含基础架构、流程规范和质量标准三层&#xff0c;提高AI的可控性、一致性和效率。文章详解设计原则、创建步骤和最佳实践&#xff0c;通过写作、代码助手、数据…

NFT:从加密猫到数字资产新纪元的全面解析

1 NFT&#xff1a;数字世界的所有权革命在数字化生存日益深入的今天&#xff0c;我们生产、消费和传播的数字内容比以往任何时候都多。然而&#xff0c;在传统的互联网架构下&#xff0c;这些数字资产极易被复制和传播&#xff0c;导致原创者难以确权和获利。NFT​ 的诞生正是为…

AI智能体的“成长秘诀“:从强化学习到DPO算法,实现从被动执行到自我进化的飞跃【建议收藏】

智能体通过"学习与适应"能力实现从"被动执行"到"主动成长"的进化。文章详细介绍了6种核心学习方式&#xff08;强化学习、监督学习等&#xff09;和两大核心算法&#xff08;PPO与DPO&#xff09;&#xff0c;并通过SICA、AlphaEvolve和OpenEvol…

干货满满:Redis 分布式锁必避的 8 大问题及解决方案

在分布式系统中,Redis 分布式锁虽能高效解决跨服务并发冲突,但实际落地时稍不注意就会踩坑——小到数据不一致,大到服务雪崩,这些问题多源于对 Redis 特性、分布式场景复杂性的考虑不周。之前开发电商库存和订单系…

数字钱包:如何正确选择使用你的数字钱包

加密货币世界里&#xff0c;“不是你的私钥&#xff0c;就不是你的币”​ 这句格言点明了私钥管理的重要性&#xff0c;而钱包正是守护这些私钥的关键工具。了解不同类型的钱包及其安全与便利的平衡&#xff0c;对管理数字资产至关重要。下面这个表格能让你快速把握冷钱包、热钱…

学习进度 4

今天学了点机器学习相关知识。 一、机器学习到底是什么 此前对机器学习的认知停留在“让电脑自己学习”的模糊概念里,今天才算有了清晰界定:机器学习是人工智能的核心分支,本质是让计算机通过数据训练,自动学习规律…

买礼物(洛谷P1194)

题目描述又到了一年一度的明明生日了&#xff0c;明明想要买 B 样东西&#xff0c;巧的是&#xff0c;这 B 样东西价格都是 A 元。但是&#xff0c;商店老板说最近有促销活动&#xff0c;也就是&#xff1a;如果你买了第 I 样东西&#xff0c;再买第 J 样&#xff0c;那么就可以…

SSAS - 步骤一:通过VS2022新建项目

本文介绍如何通过Visual Studio 2022创建SSAS项目。 打开CMD窗口&#xff0c;输入如下命令。注意替换服务器地址和VS2022文件的目录。 runas /netonly /user:192.168.88.74\administrator "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.…

Springboot中使用activemq

1. 引入ActiveMQ的SpringBoot插件<!-- ActiveMQ --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-activemq</artifactId></dependency>2. application中增加activemq的配置spring:acti…

公路修建(洛谷P1265)

题目描述某国有 n 个城市&#xff0c;它们互相之间没有公路相通&#xff0c;因此交通十分不便。为解决这一“行路难”的问题&#xff0c;政府决定修建公路。修建公路的任务由各城市共同完成。修建工程分若干轮完成。在每一轮中&#xff0c;每个城市选择一个与它最近的城市&…