新闻详情

新闻详情

首页 / 资讯中心 / 详情

Java入门实战:ArrayList实现学生管理系统,搞懂集合底层与增删改查

发布时间:2026/10/2 13:08:09来源:尧图网络
Java入门实战:ArrayList实现学生管理系统,搞懂集合底层与增删改查
在Java入门这条路上十个教程有八个会让你拿“ArrayList”练手而练手的项目十有八九是“学生管理系统”。说实话这个组合常见到有点俗但等你真把它们跑通了面向对象、容器、增删改查这些基础才算真正长在身上。我这些年带过不少新人也帮人改过不少这种小系统发现一个很有意思的现象代码量差不多但有些人写着写着就理解了ArrayList的底层逻辑有些人只是把别人的代码抄了一遍面试一问细节就露馅。所以这篇我就把这个被写烂了的项目拆开从需求设计到代码实现再到各种坑一次讲透保准你写完这个系统再去翻Java面试题里那些ArrayList相关的问题会轻松很多。这个系统本身不复杂用Java语言基于ArrayList这个容器来管理学生对象实现添加、删除、修改、查询、排序、统计这些基本功能。它很适合初学Java的人、准备校招/实习面试的人以及那些想快速复习集合和面向对象的人。接下来我用实际项目串一遍把每一步背后“为什么这么做”也讲清楚而不是丢一堆代码让你自己看。1. 项目到底在做什么先拆需求再选容器1.1 学生管理系统的核心需求清单我们先把“学生管理系统”这个模糊的词拆成可以落地的功能点。一个控制台版的系统至少要满足这么几件事能保存多条学生信息每个学生有学号、姓名、年龄、班级等基本信息能随时往系统里添加新学生能根据学号或姓名找到某个学生能删除某个学生能修改某个学生的信息能把所有学生列出来看一遍能按某个字段排序比如按学号排序或按年龄排序能做一些统计比如统计男女比例、平均年龄、各班人数这个清单基本就是最小可行产品。你可能会问直接用数组不行吗行但是很痛苦。数组长度固定学生人数不确定添加一个学生你得先考虑数组满了怎么办删除一个学生你得手动移动后面的元素。而ArrayList是动态数组自动扩容删除时封装了移动逻辑天生适合这种“数量不确定、频繁增删”的场景。1.2 为什么选ArrayList而不是数组、LinkedList很多新手选容器时是凭感觉这里我给一个特别实在的选型逻辑。ArrayList底层是数组通过下标访问元素的速度是O(1)非常适合“随机访问”。学生管理系统里最常见的操作是什么遍历列表、按照学号定位到某个学生这些都是数组的强项。往里追加元素时均摊时间复杂度也是O(1)只有在扩容那一刻需要重新拷贝数组但ArrayList扩容是1.5倍增长实际使用中拷贝次数并不多。那为什么不选LinkedListLinkedList底层是双向链表插入删除头部元素很快但按索引访问是O(n)。学生管理系统又不需要频繁在头部插入遍历时还会因为节点分散导致缓存不命中。在这种小项目里感知不强但面试时你总得说得出为什么。我的建议很简单90%的业务场景List接口下无脑用ArrayList就行LinkedList只有在你明确了“频繁头部操作”时才考虑。ArrayList还有一个隐藏优势它实现了RandomAccess接口这是一个标记接口表示支持快速随机访问。遍历时用for循环加get(index)会比迭代器更快虽然差距在小数据量下看不出来但这是面试官很喜欢埋的一个考点后面我详细说。1.3 得先想清楚这个项目练的不是ArrayList API是面向对象很多同学写这个项目时会把所有代码堆在一个main方法里定义一个ArrayList 把学生信息拼接成字符串存进去。这样做功能也能跑但写完你什么都学不到。正确做法是把“学生”抽象成一个类把“学生管理器”抽象成另一个类。学生类负责描述一个学生长什么样、有哪些属性、如何对外展示自己管理器类负责维护一个ArrayList 对外提供各种操作方法。这样代码结构清晰也符合单一职责原则。面试问“什么是面向对象”时你直接举这个项目的例子比背概念强一百倍。所以接下来的实现会分成两个核心类Student实体类和StudentManager业务类主程序只负责菜单交互。这个分层思路以后做任何管理系统都通用只是把ArrayList换成别的存储介质而已。2. 从零开始搭环境JDK配置、IDE选择、第一个工程2.1 环境变量配置别在这一步卡死不管你是Windows还是Mac跑Java项目之前必须先装JDK。我推荐装JDK 8或JDK 17前者是很多公司的生产版本后者是现在主流LTS版本面试中也常问区别。下载安装后要配环境变量JAVA_HOME并把%JAVA_HOME%\bin加到Path里。很多新手在这里卡住其实就三条验证命令java -version javac -version echo %JAVA_HOME% # Windows echo $JAVA_HOME # Mac/Linux如果javac提示不是内部或外部命令说明Path没配好如果java能执行而javac不能大概率是只装了JRE而不是JDK。这个排查思路很固定笔试环境里也经常让你配Java环境记住就行。IDE我建议直接用IntelliJ IDEA Community版免费够用。新建工程时选Java项目不用Maven也行因为这个小项目没有任何第三方依赖学习阶段越简单越好。2.2 把Student类写出来一个干净的实体类长什么样实体类设计是这个项目里最见功底的部分。一个规范的Student类至少要包含这些部分public class Student { private String id; // 学号业务上的唯一标识 private String name; // 姓名 private int age; // 年龄 private String gender; // 性别 private String className; // 班级 public Student() { } public Student(String id, String name, int age, String gender, String className) { this.id id; this.name name; this.age age; this.gender gender; this.className className; } // 每个属性都要有对应的getter和setter这里省略实际代码要补全 Override public String toString() { return Student{ id id \ , name name \ , age age , gender gender \ , className className \ }; } }这里有几个值得说的细节。第一为什么属性全是private因为封装。外部不能直接改学生学号必须通过setter校验。比如年龄不能是负数、学号不能为空这些逻辑都可以塞进setter里保证数据合法性。第二为什么学号用String而不是int因为学号可能是2024001前面带零用int会丢。而且学号本身不参与算术运算本质上它是一个标识符不是数值。第三toString()一定要重写否则你用System.out.println(student)打印的是对象的地址格式是Student1a2b3c4d调试时根本看不出数据。重写成易读格式后面遍历输出会非常方便——这也是Java里“万物皆对象”的一个直观体现默认的toString来自Object类而我们覆盖了它的行为。2.3 重写equals和hashCode这件事要养成条件反射在Student类里还有一个很多人会漏掉的点如果你希望“学号相同就是同一个学生”就必须重写equals方法。ArrayList的contains、remove(Object)等方法本身依赖equals判断默认的equals比较的是对象引用所以两个属性完全一样的Student对象在ArrayList眼里是不同的。我见过很多人在系统里写了“按学号查找”的逻辑结果拿contains去判断一直返回false就是因为没重写equals。标准的写法是这样Override public boolean equals(Object o) { if (this o) return true; if (o null || getClass() ! o.getClass()) return false; Student student (Student) o; return Objects.equals(id, student.id); } Override public int hashCode() { return Objects.hash(id); }重写equals时还要连hashCode一起重写这是Java的硬性约定。如果两个对象equals相等那它们的hashCode必须相等否则后续一旦把这些对象放进HashSet、HashMap就会出现逻辑不一致。这个项目的存储是ArrayList不强制要求hashCode但为了以后扩展我建议你从一开始就把这两个方法写对。顺便说一句这里可以用String的equals来做学号比对但既然Student已经封装好了更应该让Student自己告诉外界“我和谁相等”。这就是面向对象里“消息传递”的思想。3. 核心功能模块实现StudentManager里的增删改查3.1 管理器类的基本框架StudentManager类的核心就是用ArrayList存学生对象然后提供各种操作。先定义成员变量import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Scanner; public class StudentManager { private ListStudent students new ArrayList(); // 所有操作方法... }这里为什么用List 接口类型而不是直接用ArrayList 因为面向接口编程。今天你用ArrayList明天想换成LinkedList或者自定义的List实现只需要改new后面的部分其他代码完全不用动。这也是Java课程里强调“面向对象编程”的一层意思不是语法炫技是实实在在降低后期维护成本。3.2 添加学生先校验学号唯一再决定要不要插入添加学生的逻辑表面上只是一个list.add(student)但实际上有个关键判断学号不能重复。你可以这样设计public boolean addStudent(Student student) { for (Student s : students) { if (s.getId().equals(student.getId())) { System.out.println(学号已存在添加失败); return false; } } students.add(student); return true; }注意这里用循环遍历判断而不用contains是因为我们还没重写equals时只能手动比较id用contains默认比较对象的引用完全无效。等前面Student类重写了equals这里可以直接写成students.contains(student)可读性会好很多。两种方式都行重点是你得知道contains底层的判断逻辑是依赖equals的。添加功能看起来简单但它教会你一件事数据进系统之前要校验而不是等后期出问题再补救。学号重复、姓名为空、年龄为负都应当在入口拦截。3.3 删除学生一个Remove操作藏着两个大坑删除是新手最容易被绊倒的地方。先看最简单的写法public boolean removeStudent(String id) { for (int i 0; i students.size(); i) { if (students.get(i).getId().equals(id)) { students.remove(i); return true; } } return false; }这个写法用for循环加下标remove成功后就return不会出问题。但很多人会习惯性地写成这样for (Student s : students) { if (s.getId().equals(id)) { students.remove(s); } }一旦你在增强for循环遍历的同时调用了list.remove(s)程序大概率抛ConcurrentModificationException。原因很底层ArrayList内部的modCount修改次数和迭代器维护的expectedModCount不一致迭代器发现这个集合在遍历过程中被“外部”修改了就会快速失败。这个异常是面试高频题但面试官更想听到你会如何规避。正确做法有几种一是用普通for循环加下标删除后立刻break二是用迭代器的remove方法三是用removeIf。Java 8以后最简洁的方式是students.removeIf(s - s.getId().equals(id));这个方法内部通过迭代器完成遍历删除不会抛异常而且一行搞定。但如果你想在面试中展示基本功建议把迭代器版本也写一遍理解它为什么要用it.remove()而不是list.remove(it.next())IteratorStudent it students.iterator(); while (it.hasNext()) { Student s it.next(); if (s.getId().equals(id)) { it.remove(); return true; } }这里it.remove()会同步更新expectedModCount所以迭代不会被打断。这个机制是读ArrayList源码时最值得画圈的地方。3.4 修改学生索引定位与学号不可变原则修改学生信息时同样面临一个问题到底能不能改学号我的建议是在业务中把学号当作唯一标识不允许修改。要修改的只是姓名、年龄、性别、班级这些属性。实现思路是先按学号找到索引再对那个位置上的Student对象调setterpublic boolean updateStudent(String id, String newName, int newAge) { for (int i 0; i students.size(); i) { Student s students.get(i); if (s.getId().equals(id)) { s.setName(newName); s.setAge(newAge); return true; } } return false; }注意一个重要的现象这里并没有“把新的Student对象放回list”这个操作。因为s是list中那个对象的引用通过s修改属性ArrayList里保存的对象本身就变了。这跟基本数据类型完全不同是引用传递带来的效果。很多人学Java学到这里会迷糊这个项目恰好能把“对象引用”这个概念做实。3.5 查找和遍历for循环、增强for和迭代器怎么选查找学生有几种做法按学号查、按姓名查、模糊查。按学号找唯一一个public Student findById(String id) { for (Student s : students) { if (s.getId().equals(id)) { return s; } } return null; }按姓名查可能出现重名需要返回列表public ListStudent findByName(String name) { ListStudent result new ArrayList(); for (Student s : students) { if (s.getName().equals(name)) { result.add(s); } } return result; }这里有个设计技巧用一个新的ArrayList来装查询结果而不是直接返回原list的子列表。原因是原list后续可能被修改直接返回内部集合会破坏封装。面试时可能会让你说说“为什么返回副本”你可以从安全角度去解释。那遍历到底用哪种方式分三种情况如果只需要读数据普通for循环加get(i)效率最高如果需要边遍历边删除用迭代器或removeIf如果只是无脑看一遍增强for最简洁。这个选择题基本就是面试官考察“ArrayList使用细节”的标准套路。4. 进阶功能排序、统计、输入校验把系统做得像样4.1 排序功能Collections.sort与Comparator实战学生管理系统加排序功能后才真正有点“系统”的样子。最常见的是按学号排序和按年龄排序。Java里给ArrayList排序最正统的方式是Collections.sort(List, Comparator)Java 8之后也可以用list.sort(Comparator)。按年龄从小到大的写法students.sort(Comparator.comparingInt(Student::getAge));按学号排序因为学号是String直接比较字符串即可students.sort(Comparator.comparing(Student::getId));如果你不想用Lambda想看看完整匿名内部类长什么样students.sort(new ComparatorStudent() { Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } });这里有个隐蔽的坑用o1.getAge() - o2.getAge()可能会出现整型溢出但年龄范围正常时没问题。更稳妥的写法是Integer.compare(o1.getAge(), o2.getAge())。这种细节就是区分“背答案”和“真理解”的分水岭。想了解经典排序算法的也可以自己用冒泡排序写一版for (int i 0; i students.size() - 1; i) { for (int j 0; j students.size() - 1 - i; j) { if (students.get(j).getAge() students.get(j 1).getAge()) { Student temp students.get(j); students.set(j, students.get(j 1)); students.set(j 1, temp); } } }冒泡排序在面试里常被问到但实际项目中没人会用。我建议你写一遍冒泡作为练习然后日常还是用Comparator。顺便说一句蓝桥杯这类竞赛或者面试手撕算法时排序的底层原理还是要懂但工程上永远优先用现成的、经过优化的工具方法。4.2 统计功能循环聚合顺便把元数据封装起来统计功能包括总人数、男生人数、女生人数、平均年龄、班级人数分布等。最简单的方式是循环累加public int countByGender(String gender) { int count 0; for (Student s : students) { if (s.getGender().equals(gender)) { count; } } return count; }平均年龄public double getAverageAge() { if (students.isEmpty()) { return 0; } int sum 0; for (Student s : students) { sum s.getAge(); } return (double) sum / students.size(); }注意除法时把sum先强转成double否则两个整数相除会直接截断小数。这个坑太常见了尤其是在做统计报表时用int除以int导致结果少个0。如果想统计各个班级分别多少人用HashMapString, Integer来分组会更清晰MapString, Integer countByClass new HashMap(); for (Student s : students) { countByClass.put(s.getClassName(), countByClass.getOrDefault(s.getClassName(), 0) 1); }这种模式在以后开发中非常常用而且面试问“怎么统计一个List里每个元素出现次数”答案就是这个套路。你可以把它顺手加进这个学生管理系统里作为一个小扩展。4.3 用户输入校验Scanner的正确打开方式控制台项目的命门其实是Scanner用得好不好。新手最容易犯的错是数字输入和字符串输入混用导致nextInt之后nextLine读不到东西。举个例子如果先输入年龄用nextInt()再输入姓名用nextLine()你会发现姓名直接跳过了。原因是nextInt()只读取数字把后面的换行符留在了缓冲区nextLine()读到的是一个空行。解决办法有两个全部用nextLine读进来再用Integer.parseInt转换或者在nextInt之后额外调一次nextLine()来吞掉换行符。我个人更推荐第二种加一个简单的输入解析工具比如private static int readInt(Scanner scanner) { try { return Integer.parseInt(scanner.nextLine().trim()); } catch (NumberFormatException e) { return -1; // 表示输入非法 } }这样主菜单里每次读年龄都很稳定。还有一个小细节Scanner用完要关吗控制台程序里如果关了System.in后续再想读输入就会报NoSuchElementException所以保持不关程序结束后由JVM自己回收。如果这个程序被集成到单元测试里关闭Scanner反而会污染测试环境。4.4 用户界面的循环控制while switch怎么跳出干净接下来是主程序的骨架。一个命令行管理系统不需要花哨界面但交互要清晰。我习惯用while循环包住菜单switch做分发退出用break加标志位public static void main(String[] args) { Scanner scanner new Scanner(System.in); StudentManager manager new StudentManager(); boolean running true; while (running) { System.out.println( 学生管理系统 ); System.out.println(1. 添加学生); System.out.println(2. 删除学生); System.out.println(3. 修改学生); System.out.println(4. 查找学生); System.out.println(5. 显示所有学生); System.out.println(6. 排序); System.out.println(7. 统计); System.out.println(0. 退出); System.out.print(请选择); int choice readInt(scanner); switch (choice) { case 1: manager.addStudent(inputStudent(scanner)); break; case 2: // ... case 0: running false; break; default: System.out.println(无效选项请重新输入); } } }这里有一个很值得讲的设计把每个功能封装成单独的方法主流程只负责调度。如果你把所有逻辑都写在case分支里一旦功能变多main方法会膨胀到没法看。这种“高内聚低耦合”的写法以后学MVC、学设计模式时会反复遇到。还有switch语句中每个case后的break千万别漏。漏了break程序会继续执行下一个case这是Java基础里最经典的语法错误之一。虽然现在的IDE会提示但考场上没人提示你。5. 新手最容易踩的坑问题排查与避坑技巧实录5.1 ArrayList删除时下标越界和元素移位问题删除操作还有个特别容易忽略的细节ArrayList删除中间元素后后面的元素会自动前移如果你想通过下标连续删除多个符合条件的对象下标是会变的。比如下面这段代码你以为删掉所有的“张三”实际上跳过了某些元素for (int i 0; i students.size(); i) { if (students.get(i).getName().equals(张三)) { students.remove(i); } }第一次删除索引2的元素后原来索引3的元素跑到了索引2但循环里的i已经加到了3于是这个被移过来的元素就没被检查到。修改办法是删除后i--或者用倒序遍历。这是ArrayList操作里最高频的坑同时也解释了一个原理动态数组的删除本质上是数组元素的整体移动时间复杂度O(n)。5.2 为什么我的contains和indexOf总是返回-1如果你没有在Student类里重写equals那么contains和indexOf会比较对象引用。你new出来的Student和ArrayList里存的Student虽然是同样的学号、同样的姓名但是不同的对象所以contains返回falseindexOf返回-1。理解了这一点下次面试被问“ArrayList如何判断两个对象相等”你就可以直接答默认使用Object.equals而Object.equals比较的是引用相等所以业务对象通常要重写equals方法。再多说一句重写equals时hashCode也要跟着重写考虑到HashMap的存储逻辑。5.3 程序能跑但控制台中文乱码怎么处理Windows上跑Java控制台程序经常会遇到中文乱码。主要原因有几种源代码文件的编码和编译运行编码不一致或者控制台默认编码不是UTF-8。IDEA里可以在Settings里把文件编码统一设为UTF-8也可以在运行时加JVM参数-Dfile.encodingUTF-8。这里有个隐藏知识点Java源文件编译时javac默认是按照平台编码读取源文件的。如果不一致可能编译报错“不可映射的字符”。大部分情况下把IDEA的全局编码设成UTF-8问题就解决了。这个细节虽然和ArrayList没关系但它是做一个完整Java项目的必修课。5.4 Scanner输入空数据导致ArrayIndexOutOfBoundsException很多学生在输入学生信息时直接按回车会导致数组越界或者NumberFormatException。这个问题的根源是没有对空输入做处理。我的习惯是给输入工具方法加一个非空判断比如读取学号时如果trim后是空字符串就提示重新输入而不是把空数据传给Student对象。这样既能提升程序的健壮性也能让你在coding style上比同龄人更进一步。5.5 列表为null和列表为空是两种完全不同的事写管理系统时有人喜欢在类里先声明一个ArrayList变量但不初始化直到添加时才new。结果在显示所有学生时如果还没添加过list是null循环遍历直接NullPointerException。正确做法是声明时就初始化private ListStudent students new ArrayList();这是一个非常基础但极其重要的习惯。在面试或实际开发中空集合和null集合必须分清楚我们一般约定方法返回值不要返回null而是返回空集合这样调用方就不容易踩空指针。Java 9以后可以用List.of()返回空List但那个是不可变集合不能add小项目里还是直接new ArrayList最省心。6. 这个系统还能怎么扩展从学生管理到选课、考评系统6.1 学生选课管理系统最容易想到的升级方向题目里提到过“学生选课管理系统”这本质上就是“学生管理系统”的加长版。你需要引入第二个实体类Course以及“学生选课关系”。在纯ArrayList版本里可以给Student类增加一个List 字段private ListCourse courses new ArrayList();然后在StudentManager里增加方法public boolean selectCourse(String studentId, Course course) { Student s findById(studentId); if (s null) { return false; } if (s.getCourses().contains(course)) { return false; // 已选过 } s.getCourses().add(course); return true; }这时你又会发现Course同样需要重写equals否则contains课程会失效。你会发现前面在Student类里练的基本功在这里原封不动地用上。这就是项目递进的意义不是重复劳动是齿轮咬合。6.2 学生综合考评管理系统需要更强的数据组织能力综合考评系统比学生管理更复杂因为每个学生的成绩有很多维度。这里ArrayList依然可以用来保存所有考评记录但单一容器已经不够了通常要配合HashMap按学期或课程分组。比如MapString, ListScore scoreMap new HashMap();key是课程名value是对应成绩列表。这时候你就能体会Java容器不是孤立存在的ArrayList和HashMap经常配合使用。你去翻真实项目的源码会发现“List套Map”“Map套List”这种组合比比皆是。学生管理系统作为一个练习项目正好是接触这些组合的入口。6.3 数据持久化ArrayList只是内存里的数据还有一个不能回避的问题ArrayList存的数据程序一关就没了。想让它持久保存有三种进阶路线写文件、用序列化、连数据库。写文件最简单可以每行存一个学生的信息读文件时再解析回Student对象用ObjectOutputStream可以做对象序列化但要注意序列化版本号serialVersionUID连数据库则是工程界的主流JDBC或MyBatis。我建议学完这个系统后至少给它加一个“保存到文本文件”和“从文件加载”功能。这个过程能让你第一次真实感受到“序列化”“IO流”“数据解析”这三个词的含义。等你将来用MySQL替换掉ArrayList时你会反过来理解ArrayList只是程序运行时的存储容器而数据库是持久化存储两者定位完全不同。6.4 这条路线学完对应什么面试考点这个系统几乎可以把Java基础的核心考点串联起来面向对象类、封装、继承、多态容器ArrayList扩容机制、与LinkedList的区别、fail-fast常用APIequals、hashCode、toString重写排序Comparable与Comparator异常处理ConcurrentModificationException、NumberFormatExceptionIO流扩展文件读写泛型List我见过很多面试题比如“ArrayList的默认容量是多少”“扩容时增长多少倍”“ArrayList和Vector有什么区别”“为什么线程不安全”“如何实现线程安全”这些问题都可以以这个项目为引子去复习。你甚至可以这样跟面试官讲我写学生管理系统时用ArrayList保存学生对象遇到并发添加时会出问题所以我查了CopyOnWriteArrayList的适用场景。这一句话就能让面试官觉得你不只是会抄代码而是真的追问过原理。7. 最后再分享一点个人体会这个项目我前前后后带人写过很多遍每次都有新感悟。最大的体会是写完“能跑”只是第一步接下来一定要自己给自己提需求比如“如果学号重复怎么办”“如果删除时找不到怎么办”“如果输入的是负数怎么办”。把这些边缘情况一个个处理掉你的代码才叫系统不然只是个脚本。另外我强烈建议你把这个系统用“最小原型 持续重构”的方式写三遍第一遍跟着教程抄第二遍关掉教程自己写第三遍尝试增加扩展功能。三遍下来ArrayList就再也不会只是你简历上的一个名词。这个小项目的上限其实很高它承载了Java面向对象思想中最重要的一环用容器组织对象用对象模拟现实业务。把这个地基打牢固后面学什么框架都会顺很多。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

浏览器本地缓存选型:三套 API 的边界与避坑 2026/10/2 14:34:46

浏览器本地缓存选型:三套 API 的边界与避坑

前端面试里问"浏览器本地缓存有几种",多数人能报出 localStorage、sessionStorage、IndexedDB 这三个名字。但真到项目里,大多数人的写法就是 localStorage.setItem 一把梭,顶多再套一层 JSON.stringify。我在几个中后台项目里都碰…

阅读更多 →
Linux DHCP配置文件深度解析:作用域、安全策略与故障排查 2026/10/2 14:34:46

Linux DHCP配置文件深度解析:作用域、安全策略与故障排查

1. 为什么一份看似简单的DHCP配置文件,能决定整个局域网的“生死” 在Linux服务器运维现场,我见过太多次这样的场景:新部署的办公网络明明物理连通性完好,但几十台电脑开机后集体卡在“正在获取IP地址”界面,进度条纹丝…

阅读更多 →
C++ std::thread实战指南:创建、管理、传参与生命周期避坑 2026/10/2 14:34:46

C++ std::thread实战指南:创建、管理、传参与生命周期避坑

开篇先聊个特别常见的场景:前两天我接手一个内部工具,业务同学反馈“界面点一下卡三秒”。拉下来一查,主线程里直接跑了一大段字符串解析加文件写入,整个消息循环被堵死。这种问题,多数人第一反应就是“上多线程”&…

阅读更多 →
从零搭建AI工程:模型选型、Agent闭环与评测落地的实战指南 2026/10/2 14:34:39

从零搭建AI工程:模型选型、Agent闭环与评测落地的实战指南

有一类项目叫 ai-engineering-from-scratch,真正做完做完、做扎实的人不多。它不是什么算法刷榜,也不是拿个开源模型跑通 demo 就收工,而是从零开始,把一个 AI 想法变成稳定、可维护、可评估、能上线的东西。这几年我做过不少类似…

阅读更多 →
宇树Go2机器狗深度拆解:运动控制、二次开发与行业应用 2026/10/2 14:34:39

宇树Go2机器狗深度拆解:运动控制、二次开发与行业应用

1. 机器狗能做什么:从"玩具"到"生产力工具"的跨越说实话,这几年机器狗从实验室里的稀奇玩意儿,一步步变成大家看得见摸得着的产品,宇树(Unitree)功不可没。我最早接触宇树还是Go1时期&…

阅读更多 →
AI对话App开发实战:从项目创建到运行上线的完整链路 2026/10/2 14:34:38

AI对话App开发实战:从项目创建到运行上线的完整链路

要说这两年移动端最火的应用形态,AI对话App绝对排得上号。从大厂到独立开发者,大家都在琢磨怎么把一个能聊天的智能助手塞进手机里。我最近刚好完整走了一遍从项目创建到运行上线的全流程,踩了不少坑,才总结出一套还算顺手的做法。…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉