Scala学习记录,case class,迭代器

case class

case class创建的对象的属性是不可改的
创建对象,可以不用写new
自动重写:toString, equals, hashCode, copy

自动重写方法:toString,equals,hashCode,copy

小习一下

1.case class 的定义语法是什么

        基本形式:case class关键字后接类名,类名通常采用大写字母开头的驼峰命名法。然后是一对圆括号,括号内是类的参数列表,参数的格式为参数名:参数类型,多个参数之间用逗号分隔: case class ClassName(parameter1: Type1, parameter2: Type2, /*...*/)

2.case class有哪些作用
  1. 数据建模与封装

    • 方便的数据组合:case class 可以有效地将多个相关的数据项组合成一个逻辑单元。

    • 传递数据的容器:它可以作为一种数据容器,在函数之间或者不同的模块之间传递复杂的数据。

  2. 支持模式匹配

    • 默认的不可变性:case class 的实例默认是不可变的。所有的属性都是以val(值)的形式定义的,即:其属性不能被修改。

    • 函数式编程友好:case class 提供了一种简单的方式来创建和使用不可变数据,有助于编写更加纯粹的函数式代码,如对数据进行转换、映射等操作,而不用担心副作用。

  3. 不可变数据结构的实现

  4. 方便的复制与更新机制

    • copy方法的使用:case class 提供了copy方法,用于创建一个基于现有实例的新实例,并可以有选择地修改某些属性。

3.case class的特点有哪些
  1. 自动生成方法

    • equalshashCode方法

    • toString方法

  2. 属性为val默认不可变性

  3. 解构支持方便数据提取

  4. 伴生对象自动生成

  5. 继承和密封性(与sealed trait结合)

  6. 1.层次结构控制:当case classsealed trait结合使用时,可以构建一个受控制的继承层次结构。

4.case class和普通class在那些方面有区别
  1. 构造函数相关差异

    • 参数默认可见性

      • case class:在case class中,构造函数的参数默认是val(对于不可变数据),这意味着这些参数是公开可读的,并且不能在外部重新赋值。

      • 普通 class:普通class的构造函数参数默认是私有的,需要通过自定义的访问器方法(如gettersetter)来控制对参数的访问和修改。

    • 自动生成的方法

      • case classcase class会自动生成apply方法(在伴生对象中)用于方便地创建实例,还会生成unapply方法用于模式匹配。

      • 普通 class:普通class不会自动生成这些方法,需要开发者自己根据需求编写构造函数和其他相关方法。如果要实现类似case classapply功能,需要在伴生对象(在 Scala 中)或者静态方法(在 Java 等语言中)中手动定义创建实例的方法。

    • 构造函数的用途

      • case class:构造函数主要用于初始化不可变的数据,并且这些数据可以方便地通过模式匹配等方式进行处理。

      • 普通 class:普通class的构造函数除了初始化数据外,还可能用于初始化可变的数据成员,并且可以在构造函数中进行复杂的初始化逻辑,如资源分配、数据库连接等操作。

  2. 数据可变性差异

    • 默认行为

      • case class:如前面提到的,case class默认是不可变的,这是因为其构造函数参数是val。这种不可变性有助于在函数式编程和并发编程中避免数据被意外修改。

      • 普通 class:普通class的数据成员可以是可变的(通过var定义)或者不可变的(通过val定义),开发者可以根据具体需求来选择。例如,一个用于记录游戏状态的普通class可能有可变的成员来反映游戏中的动态变化。

    • 修改数据的方式

      • case class:如果要修改case class的数据,通常会使用copy方法。例如,对于case class Book(title: String, author: String),可以通过book.copy(title = "New Title")来创建一个新的book实例,其标题被修改为New Title

      • 普通 class:对于普通class,如果数据成员是可变的,可以直接通过访问器方法(如setter)来修改。如果是不可变的,可能需要像case class一样创建一个新的实例来更新数据。

  3. 模式匹配支持差异

    • 直接支持程度

      • case classcase class在模式匹配中有很好的支持。可以直接在模式匹配表达式中使用case class的构造函数参数进行解构。。

      • 普通 class:普通class在模式匹配中没有这种直接的支持。要让普通class参与模式匹配,通常需要在伴生对象中定义unapply方法,这个过程相对复杂。

  4. 方法自动生成差异

    • equalshashCodetoString方法

      • case classcase class会自动生成equalshashCodetoString方法。equals方法基于构造函数参数来判断两个case class实例是否相等,hashCode方法也与构造函数参数相关,toString方法会输出case class名称和构造参数的值。

      • 普通 class:普通class不会自动生成这些方法,需要开发者手动重写这些方法来满足特定的需求。如果不重写equalshashCode方法,默认的行为可能不符合预期,尤其是在比较复杂的对象结构中。


5.case class课后练习

        1.使用case class创建图书信息类Book:包含四个属性:ID,书名,作者,价格,数量。
        2.创建一个名为BookList的可变List,它只能用来保存Book的实例。
        3.初始化三本不同的书(注意id不同就是不同的书),加入到Booklist中。
        4.添加一本已经存在的书。此时应该去修改Booklist中对应书目的数量,而不是去添加一条新数据。
        5.根据图书名称查询是否在列表中(通过遍历列表对比名称)
        6.删除指定书名的书
        7.删除指定ID的书
        8.对于图书按价格从高到低排序。
        9.遍历图书列表,并打印每本书的详细信息
        10.展示全部的总的金额

package hhimport scala.collection.mutable.ListBuffer
case class Book(id: String, name: String, author: String, price: Double, quantity: Int)object 图书馆case {def main(args: Array[String]): Unit = {// 创建可变列表 BookListval bookList = ListBuffer[Book]()// 初始化三本不同的书并加入列表val book1 = Book("1", "西游记", "吴承恩", 20, 5)val book2 = Book("2", "红楼梦", "曹雪芹", 15, 3)val book3 = Book("3", "三国演义", "罗贯中", 25, 2)bookList += book1bookList += book2bookList += book3// 添加一本已经存在的书(修改数量)val existingBook = Book("2", "红楼梦", "曹雪芹", 15, 1)addOrUpdateBook(existingBook, bookList)// 根据图书名称查询是否在列表中val bookNameToSearch = "三国演义"println(s"Is book '$bookNameToSearch' in the list? ${isBookInListByName(bookNameToSearch, bookList)}")// 删除指定书名的书val bookNameToDelete = "三国演义"deleteBookByName(bookNameToDelete, bookList)// 删除指定 ID 的书val bookIdToDelete = "3"deleteBookById(bookIdToDelete, bookList)// 对图书按价格从高到低排序val sortedBooks = bookList.sortBy(-_.price)// 遍历图书列表并打印每本书的详细信息println("Books in the list:")sortedBooks.foreach(book => println(s"ID: ${book.id}, Name: ${book.name}, Author: ${book.author}, Price: ${book.price}, Quantity: ${book.quantity}"))// 展示全部的总的金额val totalAmount = sortedBooks.map(book => book.price * book.quantity).sumprintln(s"Total amount: $totalAmount")}def addOrUpdateBook(book: Book, bookList: ListBuffer[Book]): Unit = {val existingBookIndex = bookList.indexWhere(_.id == book.id)if (existingBookIndex!= -1) {bookList(existingBookIndex) = book.copy(quantity = bookList(existingBookIndex).quantity + book.quantity)} else {bookList += book}}def isBookInListByName(name: String, bookList: ListBuffer[Book]): Boolean = {bookList.exists(_.name == name)}def deleteBookByName(name: String, bookList: ListBuffer[Book]): Unit = {val maybeBook = bookList.find(_.name == name)maybeBook.foreach(book => bookList -= book)}def deleteBookById(id: String, bookList: ListBuffer[Book]): Unit = {val maybeBook = bookList.find(_.id == id)maybeBook.foreach(book => bookList -= book)}
}

打印结果: 

迭代器定义:迭代器不是一种集合,它是一种用于访问集合的方法。

迭代器需要通过集合对应的迭代器调用迭代器的方法来访问。

支持函数式编程风格,便于链式操作。

迭代器的使用:

object Test_迭代 {def main(args: Array[String]): Unit = {val list1 =List(1,2,3,4)//1. foreach 实现list1.foreach(println)//2.迭代器//2.1构建迭代器val it = list1.iterator//2.2依次取元素while (it.hasNext){println(it.next())}val set1 =Set("apple","banana")val it2 =set1.iterator //构建迭代器while (it2.hasNext){println(it2.next())}it2.map(a => s"I like $a").foreach(println)}
}
object Test_迭代 {def main(args: Array[String]): Unit = {val list1 =List(1,2,3,4)//duplicate:复制迭代器//得到一组,两个迭代器,它们有相同的数据,但是相互独立val it = List(3,4,5,6,7).iteratorval (it1,it2) = it.duplicateprintln(it1,it2)//用第一个迭代器 来计算平均值val dataList = it1.toList//把迭代器的数据放到列表中val avg = dataList.sum / dataList.sizeprintln("平均值:"+avg)//用第二个迭代器来选出大于平均值的元素it2.filter(x => x > avg).foreach(println)}
}

 take:从当前位置开始,取几个元素,得到新的迭代器

  drop:从当前位置开始,跳过指定数量的元素,得到新的迭代器

    //take:从当前位置开始,取几个元素,得到新的迭代器val it = List(1,2,3,4,5,6,7).iterator//drop:从当前位置开始,跳过指定数量的元素,得到新的迭代器val it2 = it.drop(3)//只输出3个val it1 = it2.take(3)while (it1.hasNext){println(it1.next())}

toList的作用:把迭代器中剩余的元素保存到一个List中

 //toList的作用:把迭代器中剩余的元素保存到一个List中val it = List(1,2,3,4,5,6,7).iteratorit.next()//移动一次it.next()//移动一次while (it.hasNext){println(it.next())}val li = it.toListprintln(li)

zip方法(拉链):把两个迭代器合成一下,得到新的迭代器,长度以短的为准

 val nums = List(1,2,3).iteratorval words = List("one","two","three").iterator//zip:把两个迭代器合成一下,得到新的迭代器,长度以短的为准val it = nums.zip(words)while (it.hasNext){val p = it.next()//元组println(s"${p._1} ===== ${p._2}")}

小习一下:

1.以下关于送代器next方法说法正确的是( C )

A.它总是返回送代器中的第一个元素。
B.它返回送代器中的下一个元素,并将送代器位置向前移动一位,如果没有会返回None。
C.它返回送代器中的下一个元素,并将送代器位置向前移动一位,如果没有会抛出NoSuchElementException.
D.它可以返回送代器中的任意一个元素。

  • 分析:在 Scala 中,迭代器的next方法返回迭代器中的下一个元素,并将迭代器位置向前移动一位。如果没有下一个元素,会抛出NoSuchElementException。选项 A 错误,它不是总是返回第一个元素;选项 B 错误,没有下一个元素时不会返回None,而是抛出异常;选项 D 错误,它是按顺序返回下一个元素,不是任意一个元素。

2.duplicate方法创建的迭代器副本与原迭代器( C )

A.共享元素序列,修改其中一个会影响另一个。
B.不共享元素序列,修改其中一个不会影响另一个。
C.共享元素序列,但修改其中一个不会影响另一个。
D.没有任何关系

   分析:duplicate方法创建的迭代器副本与原迭代器共享元素序列。对其中一个迭代器的操作会影响另一个,因为它们本质上是在同一个元素序列上进行遍历。

3.对于zip方法,当两个选代器台长度不同时( B )

A.会自动补齐较短的迭代器,使其长度与较长的迭代器相同。
B.会在较短的迭代器耗尽时停上zip操作。
C.会抛出异常。
D.会重复使用较短的迭代器元素,直到与较长的送代器长度相同。

  • 分析:对于zip方法,当两个迭代器长度不同时,会在较短的迭代器耗尽时停止zip操作。选项 A 错误,不会自动补齐;选项 C 错误,一般不会抛出异常;选项 D 错误,不会重复使用较短的迭代器元素来补齐

4.toList方法对迭代器的作用是( B )

A.将迭代器中的所有元素转换为一个列表,包括已经遍历过的元素。
B.将迭代器中的剩余元素转换为一个列表。
C.将列表转换为迭代器。
D.将选代器转换为一个不可变的集合。

        分析:toList方法是将迭代器中的剩余元素转换为一个列表。选项 A 错误,不是包括已经遍历过的元素;选项 C 错误,它不是将列表转换为迭代器;选项 D 错误,它只是转换为列表,不是转换为不可变的集合这种说法不准确。

5.使用drop方法创建的子送代器( B )

A.包含原迭代器的所有元素。
B.从原迭代器的开头开始,跳过指定数量的元素后包含剩余的元素。
C.包含原选代器中指定数量的元素,从开头开始。
D.是原迭代器的一个副本,不跳过任何元素

        分析:使用drop方法创建的子迭代器是从原迭代器的开头开始,跳过指定数量的元素后包含剩余的元素。选项 A 错误,不是包含所有元素;选项 C 错误,不是从开头包含指定数量的元素;选项 D 错误,会跳过指定数量的元素,不是不跳过任何元素。

6.迭代器课后练习:

1.创建学生信息数据结构和初始数据。创建一个表示学生信息的类,case student 包含姓名、年龄和 成绩列表 [ 数学,英语,语文 ] 等属性。然后创建几个学生对象,并将它们存储在一个列表中。
2.创建选代器并进行基础遍历。为学生列表创建迭代器,使用选代器的hasNext 和next方法遍历学生信息,打印每个学生的姓名。
3.使用 duplicate 方法和筛选操作。利用 duplicate 方法创建迭代器到本。在原送代器上根据年龄条件筛选年龄>20岁的同学,在副本迭代器上根据语文成绩条件筛选>80分的同学。
4.使用zip 方法关联信息。创建一个新的列表用于存储每个学生的平均成绩(三门课的平均绩),再创建该列表的选代器。通过zip 方法将学生选代器和平均成绩选代器组合,然后打印每个学生的姓名和平均成绩。
5.打印前三名的同学信息。
6.打印从第4名开始的后3位同学的信息。
7.重新创建学生列表的迭代器,用于统计所有学生的所有成绩的总和,并打印结果。
8.再次使用该迭代器,筛选出成绩列表中有至少一个特定分数以上的学生信息,并打印他们的姓名和年龄

package Scala_CSDN.十一月
// 1. 创建表示学生信息的类并初始化学生对象列表
case class Student(name: String, age: Int, scores: List[Double])
object 迭代器1 {def main(args: Array[String]): Unit = {// 创建学生对象并存储在列表中val studentList = List(Student("小张", 18, List(88.0, 85.0, 90.0)),Student("小卢", 18, List(90.0, 97.0, 85.0)),Student("小王", 19, List(98.0, 80.0, 95.0)),Student("小朱", 21,  List(90.0, 85.0, 90.0)),Student("小沈", 19, List(88.0, 90.0, 90.0)))// 2. 创建迭代器并进行基础遍历val studentIterator = studentList.iteratorwhile (studentIterator.hasNext) {val student = studentIterator.next()println(s"学生姓名: ${student.name}")}// 3. 使用duplicate方法和筛选操作val (originalIterator, duplicateIterator) = studentList.iterator.duplicateval filteredByAge = originalIterator.filter(_.age > 20)val filteredByChineseScore = duplicateIterator.filter(student => student.scores(2) > 80)println("年龄大于20岁的同学:")filteredByAge.foreach(student => println(s"姓名: ${student.name}, 年龄: ${student.age}"))println("语文成绩大于80分的同学:")filteredByChineseScore.foreach(student => println(s"姓名: ${student.name}, 语文成绩: ${student.scores(2)}"))// 4. 使用zip方法关联信息val averageScoresList = studentList.map(student => student.scores.sum / student.scores.size)val averageScoresIterator = averageScoresList.iteratorval zippedIterator = studentList.iterator.zip(averageScoresIterator)println("学生姓名和平均成绩:")zippedIterator.foreach { case (student, averageScore) =>println(s"姓名: ${student.name}, 平均成绩: ${averageScore}")}// 5. 打印前三名的同学信息val topThreeStudents = studentList.sortBy(-_.scores.sum).take(3)println("前三名同学信息:")topThreeStudents.foreach(student => println(s"姓名: ${student.name}, 年龄: ${student.age}, 成绩总和: ${student.scores.sum}"))// 6. 打印从第4名开始的后3位同学的信息val fourthAndNextThreeStudents = studentList.sortBy(_.scores.sum).drop(3).take(3)println("从第4名开始的后3位同学信息:")fourthAndNextThreeStudents.foreach(student => println(s"姓名: ${student.name}, 年龄: ${student.age}, 成绩总和: ${student.scores.sum}"))// 7. 重新创建学生列表的迭代器,用于统计所有学生的所有成绩的总和,并打印结果val allScoresIterator = studentList.iteratorvar totalScore = 0.0while (allScoresIterator.hasNext) {val student = allScoresIterator.next()totalScore += student.scores.sum}println(s"所有学生的所有成绩总和: ${totalScore}")// 8. 再次使用该迭代器,筛选出成绩列表中有至少一个特定分数以上的学生信息,并打印他们的姓名和年龄val specificScore = 90.0val filteredStudents = studentList.iterator.filter(student => student.scores.exists(_ > specificScore))println(s"成绩中有至少一个${specificScore}分以上的学生信息:")filteredStudents.foreach(student => println(s"姓名: ${student.name}, 年龄: ${student.age}"))}
}

运行结果为:

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

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

相关文章

mysql中的EXISTS和NOT EXISTS使用详解

本文来编写一个实例说下mysql中的EXISTS和NOT EXISTS使用详解 文章目录 exists用法SQL中in, not in, exists, not exists的区别使用实例本文小结 exists用法 exists: 如果括号内子查询语句返回结果不为空,说明where条件成立,就会执行主SQL语句。如果括号…

HTB:Precious[WriteUP]

目录 连接至HTB服务器并启动靶机 使用nmap对靶机TCP端口进行开放扫描 使用curl访问靶机80端口 使用ffuf爆破一下子域 使用浏览器访问该域名 使用curl访问该域名响应头 使用exiftool工具查看该pdf信息 横向移动 USER_FLAG:adf5793a876a190f0c08b3b6247cec32…

【论文分享】三维景观格局如何影响城市居民的情绪

本次带来一篇SCI论文的全文翻译!该论文以上海LivingLine项目为例,探索利用时空Wi-Fi数据分析街道层面的城市活力。 【论文题目】Understanding street-level urban vibrancy via spatial-temporal Wi-Fi data analytics: Case LivingLine Shanghai 【题…

大数据面试题--kafka夺命连环问(前15问)

目录 1、kafka消息发送的流程? 2、Kafka 的设计架构你知道吗 3、Kafka 分区的目的? 4、你知道 Kafka 是如何做到消息的有序性? 5、ISR、OSR、AR 是什么? 6、Kafka 在什么情况下会出现消息丢失? 7、怎么尽可能保…

scala 迭代更新

在Scala中,迭代器(Iterator)是一种用于遍历集合(如数组、列表、集合等)的元素而不暴露其底层表示的对象。迭代器提供了一种统一的方法来访问集合中的元素,而无需关心集合的具体实现。 在Scala中&#xff0c…

比ChatGPT更酷的AI工具

相较于寻找比ChatGPT更酷的AI工具,这听起来似乎是个挑战,因为ChatGPT已经以它强大的综合性能在AI界大名鼎鼎。然而,每个工具都有其独特的优势,特别是在特定的应用场景下,其他AI工具可能会展现出与ChatGPT不同的魅力。接…

[极客大挑战 2019]Upload 1

[极客大挑战 2019]Upload 1 审题 看到是一个文件上传类题型。 知识点 一句话木马的注入 知识点详解 一句话木马的原理 eval()函数会将参数作为PHP代码进行执行,因此通过eval()函数中的参数v提交要执行的代码即可完成漏洞利用。语句中的符号作用是可以屏蔽函数…

Redis缓存雪崩、击穿、穿透技术解析及解决方案

在使用 Redis 缓存时,经常会遇到一些异常问题。 概括来说有 4 个方面: 缓存中的数据和数据库中的不一致;缓存雪崩;缓存击穿;缓存穿透。 关于第一个问题【缓存中的数据和数据库中的不一致】,在之前的文章…

[C++11] 包装器 : function 与 bind 的原理及使用

文章目录 functionstd::function 的基本语法使用 std::function 包装不同的可调用对象function包装普通成员函数为什么要传入 this 指针参数?传入对象指针与传入对象实例的区别 例题 :150. 逆波兰表达式求值 - ⼒扣(LeetCode) bin…

企业一站式管理系统odoo的研究——系统搭建

大纲 1. 环境准备1.1 安装操作系统1.2 更新操作系统1.3 配置用户组和用户1.3.1 创建用户组 odoo1.3.2. 创建用户 odoo1.3.3. 设置用户 odoo 的密码1.3.4. 验证用户和组1.3.5. 将用户 odoo 添加到添加sudo组:1.3.6. 切到odoo用户 2. 安装 Odoo1. 安装依赖项目2.2. 安…

今天给在家介绍一篇基于jsp的旅游网站设计与实现

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

SMA-BP基于黏菌算法优化BP神经网络时间序列预测

项目源码获取方式见文章末尾! 600多个深度学习项目资料,快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…

vue3+ts+antd 运行报错 convertLegacyToken is not a function

以上代码报错 在github上看到有将 const v3Token convertLegacyToken(mapToken); 改成 const v3Token convertLegacyToken.default(mapToken);运行时就不报错了 但是到了打包的时候还是报错 但是ctrl点击convertLegacyToken能够正常跳转过去 于是我打印convertLegacyToken 发…

StarRocks Summit Asia 2024 全部议程公布!

随着企业数字化转型深入,云原生架构正成为湖仓部署的新标准。弹性扩展、资源隔离、成本优化,帮助企业在云上获得了更高的灵活性和效率。与此同时,云原生架构也为湖仓与 AI 的深度融合奠定了基础。 在过去一年,湖仓技术与 AI 的结…

HTML之列表学习记录

练习题&#xff1a; 图所示为一个问卷调查网页&#xff0c;请制作出来。要求&#xff1a;大标题用h1标签&#xff1b;小题目用h3标签&#xff1b;前两个问题使用有序列表&#xff1b;最后一个问题使用无序列表。 代码&#xff1a; <!DOCTYPE html> <html> <he…

掌控板micropython编程实现网页实时显示板载光线传感器的值

掌控板micropython编程实现网页实时显示板载光线传感器的值 一、AJAX简介 AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一种在无需重新加载整个页面的情况下&#xff0c;能够更新部分网页内容的技术。它允许Web页面与服务器进行异步数据交换&#xff0c;这…

Linux 常用操作指令大揭秘(下)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; &#x1f6a9;用通俗易懂且不失专业性的文字&#xff0c;讲解计算机领域那些看似枯燥的知识点&#x1f6a9; 目录 &#x1f4af;…

Spring源码(十二):Spring MVC之Spring Boot

本篇将详细讨论Spring Boot 的启动/加载、处理请求的具体流程。我们先从一个简单的Spring Boot项目日志开始分析&#xff08;这里假设读者已经仔细阅读完了前面的文章&#xff0c;且对Spring源码有一定深度的了解&#xff0c;否则会看得一脸懵逼&#xff09;。 本文为2024重置…

【C语言刷力扣】13.罗马数字转整数

题目&#xff1a; 解题思路: 倒序遍历&#xff0c;若当前字符代表的数字比上一字符代表的数字小&#xff0c;即减去当前字符数字。 时间复杂度&#xff1a; 空间复杂度&#xff1a; int romanToInt(char* s) {int ans 0;int low 0;int num[26];num[I - A] 1;num[V - A]…

【Unity Bug 随记】unity version control 报 xx is not in a workspace.

可能原因是更改了仓库或者项目名称。 解决办法就是重置Unity Version Control&#xff0c;去Hub disconnect 然后重新connect cloud和UVC UVC可能连不上&#xff0c;直接进入项目就行&#xff0c;打开版本管理标签会让你重新连工作区&#xff0c;选择你的仓库和工作区 然后In…