ant构建项目迁移到gradle_Gradle这么弱还跑来面腾讯?

点击上方“刘望舒”,选择“星标”

 多点在看,就是真爱

作者: 厘米姑娘(腾讯开发妹子)| 来源 :公号 码个蛋

https://www.jianshu.com/p/1274c1f1b6a4

前言

在使用Android Studio过程中没少被Gradle坑过,虽然网上有很多简单粗暴的解决方案,但极少会说清楚缘由,所以一直想看一本叫《Android Gradle权威指南》。


不过由于书中实践内容很多,更像一本工具书,而且Gradle现已发行了好几版,因此本篇仅仅是陈列出一些大的要点,尤其是那些熟悉又陌生的名词,如果想要具体了解细节和操作流程,一定要跟着书探索哟~

  • Gradle入门

  • Groovy基础

  • Gradle构建脚本基础

  • Gradle插件

  • Java Gradle插件

  • Android Gradle插件

一. Gradle入门

1.本书环境

JDK:OpenJDK 1.8.0

Gradle:Gradle 2.14.1 All 版

IDE:Android Studio 2.2.3

Android Plugin:Android Gradle 2.2.3

Android:API 23

2.Eclipse和Android Studio

a.开发配置区别:

  • Eclipse+ADT+Ant

  • Android Studio+Gradle:Gradle比Ant更灵活,有效提高开发效率

b.Eclipse迁移到AndroidStudio两种方式:

  • 使用AndroidStudio直接导入Eclipse工程

      特点:使用AS默认推荐目录结构

  • 使用Eclipse导出Android Gradle配置文件,并转换成Gradle工程,再使用Android Studio把它作为Gradle工程导入

      特点:保留原项目结构

3.Gradle的ZIP解压后目录

  • docs:API、 DSL、指南等文档

  • init.d:gradle初始化脚本目录

  • lib:相关库

  • media:一些icon资源

  • samples:示例

  • src:源文件

  • getting-started.html:入门链接

  • LICENSE

  • NOTICE

f8723034af918e5f70ce05954e3a7707.png

4.引例:Gradle版Hello World

//build.gradle:
task hello{//定义一个任务Task名为hello
doLast{//添加一个动作Action,表示在Task执行完毕后回调doLast闭包中的代码
println'Hello World'//输出字符串,单双号均可
}
}
//终端:
gradle hello//执行build.gradle中名为Hello的任务
//输出:
Hello World

5.Gradle Wrapper

a.含义:对Gradle一层包装,便于使用统一Gradle构建

b.目录结构:

|--gradle
| |--wrapper
|  |--gradle-wrapper.jar
|  |--gradle-wrapper.properties
|--gradlew
|--gradlew.bat

bc7bb341fe091209e87ae190e04b21fe.png

  • gradle-wrapper.jar:具体业务逻辑实现的jar包

  • gradle-wrapper.properties:配置文件,包含篇配置信息如下图:

4756b63c7cb5d0c9da2574cbb7192187.png

  • gradlew:Linux下可执行脚本

  • gradlew.bat:Windows下可执行脚本

c.常用命令:

  • 生成:gradle wrapper,由Wrapper Task生成

  • 配置参数:

        - gradle wrapper --gradle-version XXX用于指定使用的Gradle版本

        - gradle wrapper --distribution-url XXX用于指定下载Gradle发行版的url地址

  • 自定义:task wrapper(type:Wrapper){ //配置信息 }

6.Gradle日志

a.日志级别:

32f700bf660e7c5bd72336e5c64bac8d.png


b.日志输出代码:

  • 使用print方法,属于quiet级别日志:println 'XX'X

  • 使用内置logger:

31695015d371a56fad5cb8956db3a238.png

c.日志输出控制:

ffc9194448327428f4baab6231c97934.png


例如,输出QUIET级别及其之上的日志信息:gradle -q tasks

7.Gradle命令行

  • 查看所有可执行tasks:./gradlew tasks

  • 强制刷新依赖:./gradlew --refresh-dependencies assemble

  • 多任务调用:./gradlew clean jar

  • 查看帮助:./gradlew -?或./gradlew -h或./gradlew -help

二.Groovy基础

一句话表明Groovy的地位:Groovy于Gradle,好比Java于Android

1.特性:

Groovy是个灵活的动态脚本语言,语法和Java很相似,又兼容Java,且在此基础上增加了很多动态类型和灵活的特性,如支持闭包和DSL

2.语法

  • 分号不必需

  • 字符串:单引号和双引号均可定义一个字符串常量,区别在于单引号不能对字符串表达式做运算,而双引号可以

task printStringVar << {
def name = "张三”
println '单引号的变量计算:${name}'
println "双引号的变量计算:${name}"
}
运行./gradlew printStringVar输出结果:
单引号的变量计算:${name}
双引号的变量计算:张三
  • 集合:以List和Map为例,介绍如何定义集合和访问集合元素

//List
task printList< def numList = [1,2,3,4,5,6];//定义一个List

println numList[1]//输出第二个元素
println numList[-1]//输出最后一个元素
println numList[1..3]//输出第二个到第四个元素
numList.each{
println it//输出每个元素
}
}
//Map
task printlnMap< def map1 =['width':1024,'height':768]//定义一个Map

println mapl['width']//输出width的值
println mapl.height//输出height的值
map1.each{
println "Key:${it.key},Value:${it.value}"//输出所有键值对
}
}
  • 方法:方法调用传参的括号可省略;return不必需,无return时会将最后一行代码作为其返回值;允许将代码块(闭包)作为参数传递

//以集合的each方法为例,接受的参数就是一个闭包
numList.each({println it})
//省略传参的括号,并调整格式,有以下常见形式
numList.each{
println it
}
  • 不是一定要定义成员变量才能作为类属性被访问,用get/set方法也能当作类属性

task helloJavaBean<      Person p = new Person()
p.name = "张三"
println "名字是: ${p.name}"//输出类属性name,为张三
println "年龄是: ${p.age}"//输出类属性age,为12
}
class Person{
private String namepublic int getAge(){//省略return
12
}
}
  • 闭包:当闭包有一个参数时,默认为it,多个参数时需要一一罗列

//单个参数
task helloClosure< customEach{
println it
}
}
def customEach(closure){
 for(int i in 1..10){
 closure(i)
 }
}
//多个参数
task helloClosure< eachMap{k,v->
 println "${k} is ${v}"
 }
}
def eachMap(closure){
def map1 = ["name":"张三","age":18]
map1.each{
 closure(it.key,it.value)
 }
}

三.Gradle构建脚本基础

1.Settings文件

  • 作用:初始化、设置工程树

  • 文件名:settings.gradle,放在Project下

  • 常用方法:include方法指定能被Gradle识别的Module

//添加:app和:common这两个module参与构建
include ':app'
project(':app').projectDir = new File('存放目录')
include':common'
project(':common').projectDir = new File('存放目录')

2.Build文件

  • Project的build.gradle:整个Project的共有属性,包括配置版本、插件、依赖库等信息

  • Module的build.gradle:各个module私有的配置文件

895721f1b95a8da9fdf59e7d65bfb8d7.png

3.Gradle任务

a.含义:指原子性操作

b.关系:一个Gradle可包含多个Project,一个 Project可包含多个Task,即每个Project是由多个Task组成的;Task是Project的属性,属性名就是任务名

c.创建

  • 以任务名创建:接受一个name参数

def task myTask = task(myTask)
myTask.doLast{
println "第一种创建Task方法,原型为Task task(String name) throws InvalidUserDataException"
}

以任务名+Map创建:Map参数用于对创建的task进行配置,可用配置如下图

2a6df2d4a8ad38d7a870b02d8c3a663b.png

def task myTask = task(myTask,group:BasePlugin.BUILD_GROUP)
myTask.doLast{
println "第二种创建Task方法,原型为Task task(String name,Map args) throws InvalidUserDataException"
}
  • 以任务名+闭包创建:常见形式

task myTask{
 doLast{
   println "第三种创建Task方法,原型为Task task(String name,Closure configureClosure)"
 }
}

以上创建方式实际上最终都会调用TaskContainter#create()方法,使用./gradlew myTask命令执行任务

d.访问

  • 通过任务名访问:名称.方法

  • 通过TaskContainter访问:tasks['名称'].方法

  • 通过路径访问:参数可以为路径或名称

   get方式:tasks.getByPath('路径/名称'),若不存在会抛出UnknownTaskException异常

      find方式:tasks.findByPath('路径/名称'),若不存在返回null

  • 通过名称访问:参数只能为名称

  get方式:tasks.getByName('名称'),若不存在会抛出UnknownTaskException异常

      find方式:tasks.findByName('名称'),若不存在返回null

可见任务名称是唯一的,这是因为TaskContainer的父类 NamedDomainObjectCopllection是个具有唯一不变名字的域对象的集合

e.依赖:在创建任务时通过dependsOn指定其依赖的任务,可以控制任务的执行顺序

task task1<    println 'hello'
}
task task2< println 'world'
}
//依赖单个任务
task task3(dependsOn:task1){
doLast{
println 'one'
}
}
//依赖多个任务
task task4{
dependsOn task1,task2
doLast{
println 'two'
}
}

当执行task4时,会发现task1、task2会先执行,再执行task4

注:操作符<< 用在Task定义上相当于doLast

f.排序:除了通过强依赖来控制任务的执行顺序,还可以通过 shouldRunAfter 和 mustRunAfter 实现

taskB.shouldRunAfter(taskA) //表示taskB应该在taskA执行之后执行,有可能不会按预设执行
taskB.mustRunAfter(taskA) //表示taskB必须在taskA执行之后执行

g.分组& 描述:分组是对任务的分类,便于归类整理;描述是说明任务的作用;建议两个一起配置,便于快速了解任务的分类和用途

def task myTask = task(myTask)
myTask .group = BasePlugin.BUILD_GROUP
myTask .description = '这是一个构建的引导任务'

h.启用 & 禁用:enable属性可以启动和禁用任务,执行被禁用的任务输出提示该任务被跳过

def task myTask = task(myTask)
myTask.enable = false //禁用任务

i.执行分析:执行Task的时候实际上是执行其拥有的actions List,它是Task对象实例的成员变量;在创建任务时Gradle会解析其中被TaskAction注解的方法作为其Task执行的action,并添加到 actions List,其中doFirst和doList会被添加到action List第一位和最后一位

4.自定义属性

Project、Task和SourceSet都允许用户添加额外的自定义属性、并对自定义属性进行读取和设置

  • 方式:通过ext属性,添加多个通过ext代码块

  • 优点:相比局部变量有广泛的作用域,可以跨Project、跨Task访问,只要能访问这些属性所属的对象即可

//给Project添加自定义属性
ext.age = 18
ext{
 phone = 13888888888
 address = 'Beijing'
}
//给Task添加自定义属性
task customProperty {
ext.inner = 'innnnnner'

doLast{
 println project.hasProperty('customProperty') //true
 println project.hasProperty('age') //true
 println project.hasProperty('inner')//返回fasle

 println "${age}"
 println "${phone}"
 println "${inner}"
 }
}

四.Gradle插件

1.作用

  • 可以添加任务到项目,比如测试、编译、打包等

  • 可以添加依赖配置到项目,帮助配置项目构建过程中需要的依赖,比如第三方库等

  • 可以向项目中现有的对象类型添加新的扩展属性和方法等,帮助配置和优化构建

  • 可以对项目进行一些约定,比如约定源代码存放位置等

Gradle本身内置许多常用的插件,如若需要还可以扩展现有插件或者自定义插件,如Android Gradle插件就是基于内置的Java插件实现的

2.扩展现有插件

a.插件种类

  • 二进制插件:实现org.gradle.api.Plugin接口的插件,可以有plugin id

  • 脚本插件:严格上只是一个脚本,可以来自本地或网路

b.应用插件:通过Project#apply()方法,有三种用法

Map参数:void apply (Map options)如下:

二进制插件:

  • id:apply plugin:'java'

  • 类型:apply plugin:org.gradle.api.plugins.JavaPlugin

  • 简写:apply plugin:JavaPlugin

脚本插件:apply from:'version.gradle'

第三方发布插件:apply plugin:'com.android.application'

注意:应用第三方发布的作为jar的二进制插件时,必须先在buildscript{}配置其classpath才能使用,否则会提示找不到该插件
//buildscript:为项目进行前提准备和初始化相关配置依赖
buildscript {
repositories {
jcenter ()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0"
}
}
apply plugin:'com.android.application

<二>闭包:void apply (Closure closure)

apply {
 plugin:'java'
}

<三>Action:void apply (Action super ObjectConfigurationActicn> action)

3.自定义插件:实现Plugin接口、重写apply()方法

五.Java Gradle插件

1.项目结构

使用Java插件要先应用进来:

apply plugin:'java'

此时会添加许多默认设置和约定,比如有以下默认项目结构:

|-example
| |-build.gradle
| |-src
|  |-main
|   |-java 源代码存放目录
|   |-resources 打包文件存放目录
| |-test
|  |-java 单元测试用例存放目录
|  |-resources 单元测试中使用的文件

2.源集(SourceSet)

  • 作用:用于描述和管理源代码(java)及其资源(resources),如访问源代码目录、设置源集属性、更改Java原代码目录等

  • 方式:通过sourceSets属性(是一个SourceSetsContainer)和sourceSets{}闭包

  • 常用属性:

861a527894d2d3f0196f95073fab71f3.png

比如,在上述Java插件默认项目结构中的main和test就是内置的两个源集,现在更改main源集的Java源文件的存放目录到src/java下:

apply plugin:'java'
sourceSets{
 main{
  java{
   srcDir 'src/java'
  }
 }
}
  • 定义新源集:通过sourceSets{}闭包添加

apply plugin:'java'
sourceSets{
 vip{
 }
}

此时会新建两个目录:src/vip/java和src/vip/resources

补充:除了SourceSet,Java插件里常用的其他属性:

ca902b89638a20fdd52793da63466135.png

3.配置第三方依赖

a.依赖方式

  • 外部依赖:依赖外部仓库,如Maven、Ivy等

  • 项目依赖:依赖项目,依赖后可以使用该项目的Java类

  • 文件依赖:如依赖Jar包,出于安全考虑不发布到Maven而是放在项目的libs文件夹下

b.具体方法

  • 对于外部依赖,需要先在repositories{}闭包里声明依赖库的位置

  • 在dependencies{}闭包添加依赖

        - 外部依赖:说明依赖库的group:name:version

        - 项目依赖:project('项目名称')

        - 文件依赖:files('文件名称'),多个文件逗号分开,或者fileTree(dir:'文件名称',include:'*.扩展名称')依赖指定文件夹下指定扩展名文件

  • 几种依赖类型

0688f8f5b8876c8b2f80902b66f551c9.png

举例:

apply plugin:'java'
repositories {
//外部依赖 依赖Maven中心库
maveCentral()
}
dependencies {
 //外部依赖 完整写法
 compile group:'com.squareup.okhttp3',name:'okhttp', version:'3.0.1'
 //外部依赖 简单写法
 compile 'com.squareup.okhttp3:okhttp:3.0.1'
 //外部依赖 指定main源集依赖
 mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
 //项目依赖
 compile project(':example')
 //文件依赖 依赖libs下两个Jar包
 compile files('libs/example01.jar', 'libs/example02.jar')
 //文件依赖 指定依赖libs下所有Jar包
 compile fileTree(dir: 'libs',include: '*.jar')
}

4.内置任务

常用几种任务:

  • build任务:构建项目

  • clean任务:删除build目录及构建生成的文件

  • assemble任务:不执行单元测试,只编译和打包

  • check任务:只执行单元测试

  • javadoc任务:生成Java格式的doc api文档

还有些通用任务、对源集适用的任务:

8c32099636ff95d164e5087786b57943.png

5.多项目构建

  • 含义:多个Gradle项目一起构建

  • 方式:通过settings.gradle配置管理多项目;在每个项目都有一个build.gradle,采用项目依赖就能实现多项目协作

//settings.gradle
include ':app'
project(':app').projectDir = new File('存放目录')
include ':base'
project(':base').projectDir = new File('存放目录')

//app/build.gradle
apply plugin:'java'
dependencies {
compile project(':base')
}

6.发布构件

  • 构件:Gradle构建的产物,如Jar包、Zip包等

  • 意义:发布构建给其他工程使用,可以发布到本地目录、Maven、Ivy等

  • 方式:明确构件类型,并通过artifacts{}闭包配置需要发布的构建,在uploadArchives{}上传发布构件

//以发布jar构件为例
apply plugin:'java '
task publishJar(type:Jar)
artifacts{
 archives publishJar
}
uploadArchives{
repositories{
//发布到本地目录
flatDir{
 name 'libs'
 dirs "$projectDir/libs"
}
//发布到本地Maven库
mavenLocal()
 }
}

篇幅有限,更多请阅读作者妹子的博文:

https://www.jianshu.com/p/1274c1f1b6a4

---------  END  ----------

推荐阅读

Android系统服务(一)解析ActivityManagerService(AMS)

Android PMS的创建过程

美团跨平台框架Picasso,开启大前端的未来

彻底理解cookie、session、token

你好,我是刘望舒,十年经验的资深架构师,著有两本业界知名的技术畅销书。

如果你喜欢我的文章,就给公众号加个星标吧,方便阅读。

9509e320fb6f23637c748199c46e0d4f.png

推荐一个可以让你技术快速提升的神奇地方,有兴趣的同学可以点击底部的 阅读原文 

  在看也是一种认可70785c7efac779fb6cb58e121cb43ae4.gif

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

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

相关文章

java heroku_使用Spring Boot和Heroku在20分钟内完成Java的单点登录

java heroku建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 大规模更新 我最初为本文…

如何使用SSH客户端远程操作linux系统,并启动、关闭tomcat和查看后台日志

cd … 表示回退到上一级目录 ls 表示查看当前目录下的所有文件 我们的tomcat安装路径在usr\local\yzmis\下面找 例如你要关闭信誉质量考核系统所在的tomcat&#xff0c;你要进入test下去找到apache-tomcat-6.0.14 再进入bin目录下&#xff0c;然后执行[trserver100 bin]$ ./sh…

模块pdf2image.dll加载失败_Webpack 原理从前端模块化开始

当前主流 JS 模块化方案无模块化CommonJS 规范&#xff0c;nodejs 实现的规范AMD 规范&#xff0c;requirejs 实现的规范CMD 规范&#xff0c;seajs 实现的规范&#xff0c; seajs 与 requirejs 实现原理有很多相似的地方 u ES Modules&#xff0c;当前 js 标准模块化方案注意:…

ios html正则表达式,ios 正则表达式去html标签

ios 正则表达式去html标签[2021-01-27 12:53:55] 简介:php正则表达式去掉html的方法&#xff1a;首先使用“htmlspecialchars_decode” 将特殊的HTML实体转换回普通字符&#xff1b;然后通过正则表达式“preg_replace(/]>/,,$_st系统运维正则表达式概述基础正则表达式扩展正…

java开发五年面试经验_只有经验丰富的开发人员才能教您有关Java的5件事

java开发五年面试经验深入研究Java之前需要了解的所有内容的概述 有许多工具&#xff0c;方法&#xff0c;环境和功能会改变您处理代码的方式&#xff0c;而这些通常是在学年期间不会遇到的。 虽然它在Java开发世界中迈出了第一步&#xff0c;但大多数实际学习都是在工作中进行…

c++调用cplex求解例子_视频教程 | 用Python玩转运筹优化求解器IBM CPLEX(二)

编者按优化求解器对于做运筹学应用的学生来说&#xff0c;意义重大。然而直到今天&#xff0c;放眼望去&#xff0c;全网&#xff08;包括墙外&#xff09;几乎没有一个系统的Cplex中文求解器教程。作为华人运筹学的最大的社区&#xff0c;『运筹OR帷幄』 责无旁贷&#xff0c;…

markdown 行内公式_如何轻松将笔记转为思维导图(Word、Markdown)

目录简介Markdown -> XMindWord -> XMind简介思维导图是一种一种图像式思维的工具&#xff0c;便于我们理解知识之间的逻辑关系。在我们的学习、生活中&#xff0c;我们习惯于使用word、markdown等笔记软件&#xff0c;而较少的使用思维导图。其实&#xff0c;有些时候我…

apache.camel_Apache Camel 2.18发布–包含内容

apache.camel本周发布了Apache Camel 2.18.0 。 此版本是重要版本&#xff0c;我将在此博客文章中重点介绍。 Java 8 Camel 2.18是第一个需要Java 1.8的版本&#xff08;例如&#xff0c;容易记住的Camel 2.18 Java1.8。Camel2.17 Java 1.7&#xff09;。 我们采取了谨慎的…

cors跨域_Spring Boot 中通过 CORS 解决跨域问题

(给ImportNew加星标&#xff0c;提高Java技能)转自&#xff1a;江南一点雨今天和小伙伴们来聊一聊通过CORS解决跨域问题。同源策略很多人对跨域有一种误解&#xff0c;以为这是前端的事&#xff0c;和后端没关系&#xff0c;其实不是这样的&#xff0c;说到跨域&#xff0c;就不…

逻辑建模与物理建模_架构层和建模域逻辑

逻辑建模与物理建模在讨论用于建模域逻辑&#xff08;例如事务脚本&#xff0c;表模块&#xff0c;域模型&#xff09;的PoEAA模式时&#xff0c;我注意到人们对域模型模式是最好的印象&#xff08;尽管印象不对&#xff09;。 因此&#xff0c;他们开始将其应用于所有内容。 …

html文字列表,文字列表模板

文字列表模板1、如何编辑列表模板文字列表模板存放在模板包archive文件夹中&#xff0c;命名以list_text为前缀在模板包中找到list_text.html 模板&#xff0c;复制另存为一个新模板&#xff0c;命名为list_text_自定义名称.html自定义名称可以是英文或拼音&#xff0c;但不能用…

inputstreamreader未关闭会导致oom_Linux内核OOM机制分析和防止进程被OOM杀死的方法...

问题描述Linux 内核有个机制叫 OOM killer(Out-Of-Memory killer)&#xff0c;该机制会监控那些占用内存过大&#xff0c;尤其是瞬间很快消耗大量内存的进程&#xff0c;为了防止内存耗尽而内核会把该进程杀掉。典型的情况是&#xff1a;某天一台机器突然 ssh 远程登录不了&…

centos一键清理磁盘空间_如何清理 Docker 占用的磁盘空间

Docker 很占用空间&#xff0c;每当我们运行容器、拉取镜像、部署应用、构建自己的镜像时&#xff0c;我们的磁盘空间会被大量占用。如果你也被这个问题所困扰&#xff0c;咱们就一起看一下 Docker 是如何使用磁盘空间的&#xff0c;以及如何回收。docker 占用的空间可以通过下…

mongodb dsl_具有Java DSL的Spring Integration MongoDB适配器

mongodb dsl1引言 这篇文章解释了如何使用Spring Integration从MongoDB数据库中保存和检索实体。 为了完成此任务&#xff0c;我们将使用Java DSL配置扩展来配置入站和出站MongoDB通道适配器。 例如&#xff0c;我们将构建一个应用程序&#xff0c;使您可以将订单写入MongoDB存…

Oracle 数据库中较为复杂或典型的 SQL 语句的解读

文章目录批量生成 SQL 语句/拼接字符串多表关联查询 where 子句示例&#xff08;一&#xff09;示例&#xff08;二&#xff09;普通的表间内连接查询语句关键字 distinct 用法说明Oracle 数据库的分组排序查询Oracle 数据库 cast 函数Oracle 数据库 sum 函数的高级用法Oracle…

私有方法与静态私有方法_每个私有静态方法都是新类的候选人

私有方法与静态私有方法您是否有私有的静态方法来帮助您将算法分解为更小的部分&#xff1f; 我做。 每当我编写一个新方法时&#xff0c;我就会意识到它可以是一个新类。 当然&#xff0c;我不会从所有课程中选修课程&#xff0c;但这必须是目标。 私有静态方法不可重用&#…

c语言插入排序_还有这种操作?C语言插入排序算法,一点就透

插入排序算法是所有排序方法中最简单的一种算法&#xff0c;其主要的实现思想是将数据按照一定的顺序一个一个的插入到有序的表中&#xff0c;最终得到的序列就是已经排序好的数据。更多C/C资料群文件&#xff1a;569268376直接插入排序是插入排序算法中的一种&#xff0c;采用…

Mac 如何操控远程的 Windows 电脑

文章目录使用 Remote Desktop Connection for mac 客户端第 1 步&#xff1a;Windows 电脑进行远程设置第 2 步&#xff1a;Windows 电脑设置管理员账号和密码第 3 步&#xff1a;获取 Windows 电脑的 IP 地址第 4 步&#xff1a;Mac 电脑安装远程桌面连接客户端第 5 步&#x…

map iterator_一个简单的Map Iterator性能测试

map iteratorJava Map性能有很多方面可以衡量&#xff0c;但是关键的一个是简单的单线程扫描。 这是一些针对Iterators和Java 8 Map.forEach()简单测试代码&#xff0c;以及一些图形结果。 1.性能测试困难 性能测试是一项非常困难的工作&#xff0c;精确的可重复性测试需要Jav…

学生用计算机中sto,STO 文件扩展名: 它是什么以及如何打开它?

STO 疑难解答常见的 STO 打开问题Ecru Software PRO100 不存在你尝试加载 STO 文件并收到错误&#xff0c;例如 “%%os%% 无法打开 STO 文件扩展名”。 如果是这种情况&#xff0c;通常是因为 你的计算机上没有安装 Ecru Software PRO100 for %%os%%。 由于您的操作系统不知道如…