多平台编程

支持多平台编程是 Kotlin 的主要优势之一。它减少了为不同平台编写和维护相同代码所花费的时间,同时保留了本机编程的灵活性和优势。

这就是 Kotlin Multiplatform 的工作原理。

  • Common Kotlin包括语言、核心库和基本工具。用普通 Kotlin 编写的代码适用于所有平台。

  • 借助 Kotlin 多平台库,您可以在通用和特定于平台的代码中重用多平台逻辑。公共代码可以依赖于一组涵盖日常任务的库,例如HTTP、序列化和管理协程。

  • 要与平台互操作,请使用特定于平台的 Kotlin 版本。特定于平台的 Kotlin 版本(Kotlin/JVM、Kotlin/JS、Kotlin/Native)包括对 Kotlin 语言的扩展,以及特定于平台的库和工具。

  • 通过这些平台,您可以访问平台本机代码(JVM、JS 和本机)并利用所有本机功能。

使用 Kotlin Multiplatform,花更少的时间为不同平台编写和维护相同的代码——只需使用 Kotlin 提供的机制共享它:

  • 在项目中使用的所有平台之间共享代码。使用它来共享适用于所有平台的通用业务逻辑。

  • 在项目中包含的某些平台之间共享代码,但不是全部。当您可以在类似平台上重用大部分代码时,请执行此操作。

如果您需要从共享代码访问特定于平台的 API,请使用预期和实际声明的 Kotlin 机制。

使用这种机制,公共源集定义了预期声明,平台源集必须提供与预期声明相对应的实际声明。这适用于大多数 Kotlin 声明,例如函数、类、接口、枚举、属性和注释。

<span style="background-color:var(--wh-color-backlight-main)"><span style="color:#19191c"><span style="color:var(--wh-color-text-main)"><code><span style="color:#708090">//Common</span>
<strong><span style="color:#0077aa">expect</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">randomUUID</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#9a6e3a">:</span> String</code></span></span></span>
已复制!
<span style="background-color:var(--wh-color-backlight-main)"><span style="color:#19191c"><span style="color:var(--wh-color-text-main)"><code><span style="color:#708090">//Android</span>
<strong><span style="color:#0077aa">import</span></strong> java<span style="color:#999999">.</span>util<span style="color:#999999">.</span><span style="color:#9a6e3a">*</span>
<strong><span style="color:#0077aa">actual</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">randomUUID</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> UUID<span style="color:#999999">.</span><span style="color:#dd4a68">randomUUID</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toString</span><span style="color:#999999">(</span><span style="color:#999999">)</span></code></span></span></span>
已复制!
<span style="background-color:var(--wh-color-backlight-main)"><span style="color:#19191c"><span style="color:var(--wh-color-text-main)"><code><span style="color:#708090">//iOS</span>
<strong><span style="color:#0077aa">import</span></strong> platform<span style="color:#999999">.</span>Foundation<span style="color:#999999">.</span>NSUUID
<strong><span style="color:#0077aa">actual</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">randomUUID</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#9a6e3a">:</span> String <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">NSUUID</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">UUIDString</span><span style="color:#999999">(</span><span style="color:#999999">)</span></code></span></span></span>
已复制!

用例

安卓——iOS

在移动平台之间共享代码是 Kotlin 多平台的主要用例之一。借助 Kotlin Multiplatform Mobile (KMM),您可以构建多平台移动应用程序,在 Android 和 iOS 之间共享代码,例如业务逻辑、连接性等。

查看KMM 功能、案例研究和示例

客户端服务器

代码共享可能带来好处的另一个场景是连接的应用程序,其中逻辑可以在服务器和浏览器中运行的客户端上重用。Kotlin Multiplatform 也涵盖了这一点。

所述Ktor框架是适用于连接系统构建异步服务器和客户端。

下一步是什么?

刚接触 Kotlin?访问Kotlin 入门。

文档

  • 开始使用 Kotlin Multiplatform Mobile (KMM)

  • 创建多平台项目

  • 在多个平台上共享代码

  • 连接到特定于平台的 API

教程

  • 创建您的第一个 KMM 应用程序展示了如何借助适用于 Android Studio的KMM 插件创建适用于 Android 和 iOS 的移动应用程序。创建、运行和测试您的第一个多平台移动应用程序。

  • 创建多平台 Kotlin 库教授如何创建可用于 JVM、JS 和 Native 的多平台库,并可从任何其他通用代码(例如,与 Android 和 iOS 共享)中使用。它还展示了如何编写将在所有平台上执行的测试并使用特定平台提供的有效实现。

  • 使用 Kotlin Multiplatform 构建全栈 Web 应用程序通过构建使用共享代码、序列化和其他多平台范例的客户端-服务器应用程序,教授构建面向 Kotlin/JVM 和 Kotlin/JS 的应用程序背后的概念。它还简要介绍了如何使用 Ktor 作为服务器端和客户端框架。

示例项目

KMM是建立在之上科特林多的技术,它支持其他平台的JavaScript计有,Linux和WebAssembly,和更多。

请参阅Kotlin 多平台编程支持的平台。

示例项目

查看我们的 KMM 示例项目列表以获取灵感。

影片

通过YouTube 上的Kotlin Multiplatform Multiverse视频学习 KMM 。

社区

安全

我们尽最大努力确保我们的软件没有安全漏洞。为了降低引入漏洞的风险,您可以遵循Kotlin 安全建议。

我们非常渴望和感激听到您发现的任何安全问题。要报告您在 KMM 的任何部分发现的漏洞,请直接向我们的问题跟踪器发布消息或向我们发送电子邮件。

有关我们负责任的披露流程如何运作的更多信息,请查看JetBrains 协调披露政策。

使用 Kotlin 进行服务器端开发的框架

部署 Kotlin 服务器端应用程序

Kotlin 应用程序可以部署到任何支持 Java Web 应用程序的主机中,包括 Amazon Web Services、Google Cloud Platform 等。

要在Heroku上部署 Kotlin 应用程序,您可以按照Heroku 官方教程进行操作。

AWS 实验室提供了一个示例项目,展示了如何使用 Kotlin 编写AWS Lambda函数。

Google Cloud Platform 提供了一系列教程,用于将 Kotlin 应用程序部署到 GCP,包括Ktor 和 App Engine以及Spring 和 App Engine。此外,还有一个用于部署 Kotlin Spring 应用程序的交互式代码实验室。

服务端 Kotlin 用户

Corda是一个开源的分布式账本平台,得到各大银行的支持,完全用 Kotlin 构建。

JetBrains Account是JetBrains负责整个许可证销售和验证流程的系统,100% 使用 Kotlin 编写,自 2015 年以来一直在生产中运行,没有出现重大问题。

下一步

许多初创公司和财富 500 强公司已经使用 Kotlin 开发了 Android 应用程序——请参阅Google 网站上的 Kotlin 开发人员列表。

如果您想开始使用 Kotlin 进行 Android 开发,请阅读Google 关于在 Android 上开始使用 Kotlin 的建议。

如果您不熟悉 Android 并想学习使用 Kotlin 创建应用程序,请查看此 Udacity 课程。

五:用于 JavaScript 的 Kotlin

  • Kotlin 多平台移动 (KMM) 示例

  • KotlinConf 应用

  • KotlinConf Spinner 应用程序

    Kotlin 多平台移动

    Kotlin Multiplatform Mobile ( KMM ) 是一个 SDK,旨在简化跨平台移动应用程序的创建。在 KMM 的帮助下,您可以在 iOS 和 Android 应用程序之间共享通用代码,并仅在必要时编写特定于平台的代码。例如,要实现本机 UI 或在使用特定于平台的 API 时。

    开始使用 Kotlin Multiplatform Mobile

    如果您已经熟悉 Kotlin 语言并想试用 Kotlin Multiplatform Mobile (KMM),请开始使用 KMM。如果您是 Kotlin 新手,请从这些教程开始。

    如果您想向您的团队介绍 KMM,请查看我们的建议。

    支持的平台

    KMM 支持以下移动目标:

  • Android 应用程序和库

  • ARM32 和 ARM64 平台上的Android NDK

  • ARM64(iPhone 5s 和更新版本)、ARM32(早期型号)平台上的 Apple iOS,以及基于 Intel 和 Apple Silicon 平台的桌面模拟器

  • ARM64(Apple Watch Series 4 和更新版本)、ARM32(早期型号)平台上的 Apple watchOS,以及基于 Intel 和 Apple Silicon 平台的桌面模拟器

  • Kotlin Slack:获得邀请并加入#multiplatform频道。

  • StackOverflow:订阅“kotlin-multiplatform”标签。

  • Kotlin 问题跟踪器:报告新问题。

    三:服务器端的 Kotlin

    编辑页面
    最后修改时间:2021 年 6 月 23 日

    Kotlin 非常适合开发服务器端应用程序,允许您编写简洁而富有表现力的代码,同时保持与现有基于 Java 的技术堆栈的完全兼容性和平滑的学习曲线:

  • 表现力:Kotlin 的创新语言特性,例如它对类型安全构建器和委托属性的支持,有助于构建强大且易于使用的抽象。

  • 可扩展性:Kotlin 对协程的支持有助于构建服务器端应用程序,这些应用程序可扩展到具有适度硬件要求的大量客户端。

  • 互操作性:Kotlin 与所有基于 Java 的框架完全兼容,这让您可以继续使用熟悉的技术堆栈,同时从更现代的语言中获益。

  • 迁移:Kotlin 支持将大型代码库从 Java 逐步迁移到 Kotlin。您可以开始在 Kotlin 中编写新代码,同时将系统的旧部分保留在 Java 中。

  • 工具:除了一般的强大 IDE 支持外,Kotlin 还在 IntelliJ IDEA Ultimate 的插件中提供了特定于框架的工具(例如,用于 Spring)。

  • 学习曲线:对于 Java 开发人员来说,开始使用 Kotlin 非常容易。Kotlin 插件中包含的自动化 Java 到 Kotlin 转换器有助于完成第一步。Kotlin Koans通过一系列互动练习提供了有关该语言主要功能的指南。

  • 从 5.0 版本开始,Spring利用 Kotlin 的语言特性提供更简洁的 API。该在线项目生成器允许您快速生成科特林一个新的项目。

  • Vert.x是一个在 JVM 上构建响应式 Web 应用程序的框架,它为 Kotlin提供专门的支持,包括完整的文档。

  • Ktor是由 JetBrains 构建的框架,用于在 Kotlin 中创建 Web 应用程序,利用协程实现高可扩展性,并提供易于使用和惯用的 API。

  • kotlinx.html是一种 DSL,可用于在 Web 应用程序中构建 HTML。它可以替代传统的模板系统,例如 JSP 和 FreeMarker。

  • Micronaut是一个现代的、基于 JVM 的全栈框架,用于构建模块化、易于测试的微服务和无服务器应用程序。它带有许多内置的、方便的功能。

  • 有关该语言的更深入介绍,请查看此站点上的 Kotlin 文档和Kotlin Koans。

  • Micronaut 还有很多详细的指南,展示了如何在 Kotlin 中构建微服务。

  • http4k 提供了CLI来生成完整的项目,并提供一个启动库来使用 GitHub、Travis 和 Heroku 和单个 bash 命令生成整个 CD 管道。

  • 想要从 Java 迁移到 Kotlin?了解如何在 Java 和 Kotlin 中使用字符串执行典型任务。

    • http4k是功能性工具包,占用空间很小,用于 Kotlin HTTP 应用程序,用纯 Kotlin 编写。该库基于 Twitter 的“您的服务器即函数”论文,并将 HTTP 服务器和客户端建模为可以组合在一起的简单 Kotlin 函数。

    • Javalin是一个非常轻量级的 Kotlin 和 Java 网络框架,支持 WebSockets、HTTP2 和异步请求。

    • 可用的持久性选项包括直接 JDBC 访问、JPA 以及通过其 Java 驱动程序使用 NoSQL 数据库。对于 JPA,kotlin-jpa 编译器插件使Kotlin 编译的类适应框架的要求。

    • 四:安卓版 Kotlin

      自 2019 年 Google I/O 以来,Android 移动开发一直是 Kotlin 第一。

      使用 Kotlin 进行 Android 开发,您可以受益于:

    • 更少的代码与更高的可读性相结合。花更少的时间编写代码并努力理解他人的代码。

    • 成熟的语言和环境。自 2011 年创建以来,Kotlin 不断发展,不仅作为一种语言,而且作为一个具有强大工具的整个生态系统。现在它无缝集成到 Android Studio 中,并被许多公司积极用于开发 Android 应用程序。

    • Android Jetpack 和其他库中的 Kotlin 支持。KTX 扩展向现有 Android 库添加 Kotlin 语言功能,例如协程、扩展函数、lambda 和命名参数。

    • 与 Java 的互操作性。您可以在应用程序中使用 Kotlin 和 Java 编程语言,而无需将所有代码迁移到 Kotlin。

Kotlin/JS 能够将您的 Kotlin 代码、Kotlin 标准库和任何兼容的依赖项转换为 JavaScript。Kotlin/JS 的当前实现面向ES5。

推荐的使用 Kotlin/JS 的方法是通过kotlin.jskotlin.multiplatformGradle 插件。它们提供了一种集中且方便的方式来设置和控制面向 JavaScript 的 Kotlin 项目。这包括基本功能,例如控制应用程序的捆绑、直接从 npm 添加 JavaScript 依赖项等。要获得可用选项的概述,请查看Kotlin/JS 项目设置文档。

Kotlin/JS 的用例

可以通过多种方式使用 Kotlin/JS。为了给您一些启发,这里有一份您可以使用 Kotlin/JS 的场景的非详尽列表。

使用 Kotlin/JS 编写前端 Web 应用程序

  • Kotlin/JS 允许您以类型安全的方式利用强大的浏览器和 Web API。创建、修改文档对象模型 (DOM) 中的元素并与之交互,使用 Kotlin 代码控制canvasWebGL 组件的渲染,并享受对现代浏览器支持的更多功能的访问。

  • 使用JetBrains 提供的Kotlin/JS编写完整的、类型安全的 React 应用程序,kotlin-wrappers为最流行的 JavaScript 框架之一提供方便的抽象和深度集成。kotlin-wrappers还提供了用于选择数量的相邻的技术支持喜欢react-reduxreact-routerstyled-components。与 JavaScript 生态系统的互操作性也意味着您还可以使用第三方 React 组件和组件库。

  • 使用充分利用 Kotlin 概念、表达能力和简洁性的Kotlin/JS 框架

使用 Kotlin/JS 编写服务器端和无服务器应用程序

  • Kotlin/JS 提供的 Node.js 目标使您能够创建在服务器运行在无服务器基础设施上执行的应用程序。您可以从与在 JavaScript 运行时中执行的其他应用程序相同的优势中受益,例如更快的启动速度更少的内存占用。使用kotlinx-nodejs,您可以直接从 Kotlin 代码对Node.js API进行类型安全访问。

使用 Kotlin 的多平台项目与其他 Kotlin 目标共享代码

  • 使用 Kotlin multiplatformGradle 插件时,也可以访问所有 Kotlin/JS 功能。

  • 如果您有一个用 Kotlin 编写的后端,您可以与一个用 Kotlin/JS 编写的前端共享数据模型或验证逻辑等通用代码,从而允许您编写和维护全栈 Web 应用程序

  • 您还可以在适用于 Android 和 iOS 的Web 界面和移动应用程序之间共享业务逻辑,并避免重复常用功能,例如提供围绕 REST API 端点、用户身份验证或域模型的抽象。

创建用于 JavaScript 和 TypeScript 的库

  • 您也不必用 Kotlin/JS 编写整个应用程序——您还可以从 Kotlin 代码生成库,这些可以作为模块使用,这些可以从任何用 JavaScript 或 TypeScript 编写的代码库中使用,而不管使用的其他框架或技术如何。这种创建混合应用程序的方法允许您利用您和您的团队在 Web 开发方面可能已经拥有的能力,同时帮助您减少重复工作的数量,并使您的 Web 目标与应用程序的其他目标保持一致.

  • 使用 React 和 Kotlin/JS 构建 Web 应用程序将指导您完成使用 React 框架构建简单 Web 应用程序的过程,展示类型安全的 Kotlin DSL for HTML 如何轻松构建响应式 DOM 元素,并说明如何使用第三个- 方 React 组件并从 API 获取信息,同时使用纯 Kotlin/JS 编写整个应用程序逻辑。

  • 通过构建使用共享代码、序列化和其他多平台范例的客户端-服务器应用程序,使用Kotlin Multiplatform 构建全栈 Web 应用程序教授构建面向 Kotlin/JVM 和 Kotlin/JS 的应用程序背后的概念。它还简要介绍了如何使用 Ktor 作为服务器端和客户端框架。

  • 全栈 Spring 协作待办事项列表展示了如何使用kotlin-multiplatformJS 和 JVM 目标、后端使用Spring、前端使用带有 React 的 Kotlin/JS 和 RSocket创建协作工作的待办事项列表。

  • Kotlin/JS 和 React Redux待办事项列表使用来自 npm 和 Webpack 的JS 库(reactreact-domreact-routerredux, 和react-redux)实现了 React Redux 待办事项列表,以捆绑、缩小和运行项目。

  • 苹果系统

  • iOS、tvOS、watchOS

  • Linux

  • 视窗 (MinGW)

  • 安卓NDK

  • 适用于许多平台的可执行文件

  • 用于 C/C++ 项目的带有 C 头文件的静态库或动态库

  • 用于 Swift 和 Objective-C 项目的Apple 框架

  • 静态或动态C 库

  • C、Swift 和 Objective-C框架

  • Kotlin 多平台移动文档

  • 多平台文档

  • C互操作

  • Swift/Objective-C 互操作

  • 开始使用 Kotlin/Native

  • 创建您的第一个 KMM 应用程序

  • C 和 Kotlin/Native 之间的类型映射

  • Kotlin/Native 作为动态库

  • Kotlin/Native 作为 Apple 框架

  • Kotlin 多平台移动示例

  • Kotlin/Native 源代码和示例

  • KotlinConf 应用

  • KotlinConf Spinner 应用程序

  • Kotlin/Native 源代码和示例 (.tgz)

  • Kotlin/Native 源代码和示例 (.zip)

    用于数据科学的 Kotlin

    从构建数据管道到生产机器学习模型,Kotlin 都是处理数据的绝佳选择:

    • Kotlin 简洁、易读且易于学习。

    • 静态类型和空值安全有助于创建可靠、可维护且易于排除故障的代码。

    • 作为一种 JVM 语言,Kotlin 为您提供了出色的性能和利用经过验证的真正 Java 库的整个生态系统的能力。

    交互式编辑器

    Jupyter Notebook和Apache Zeppelin等笔记本为数据可视化和探索性研究提供了方便的工具。Kotlin 与这些工具集成,可帮助您探索数据、与同事分享您的发现,或培养您的数据科学和机器学习技能。

    Jupyter Kotlin 内核

    Jupyter Notebook 是一个开源 Web 应用程序,它允许您创建和共享可以包含代码、可视化和降价文本的文档(又名“笔记本”)。Kotlin-jupyter是一个开源项目,它为 Jupyter Notebook 提供了 Kotlin 支持。

    查看 Kotlin 内核的GitHub 存储库以获取安装说明、文档和示例。

    Zeppelin Kotlin 解释器

    Apache Zeppelin 是一种流行的基于 Web 的交互式数据分析解决方案。它为Apache Spark集群计算系统提供了强大的支持,对数据工程特别有用。从版本 0.9.0开始,Apache Zeppelin 附带捆绑的 Kotlin 解释器。

    图书馆

    Kotlin 社区创建的用于数据相关任务的库生态系统正在迅速扩展。以下是一些您可能会觉得有用的库:

    Kotlin 库

    • Multik : Kotlin 中的多维数组。该库为多维数组的数学运算提供 Kotlin 惯用的、类型和维度安全的 API。Multik 提供可交换的 JVM 和本机计算引擎,以及两者的组合以获得最佳性能。

    • KotlinDL是用 Kotlin 编写并受Keras启发的高级深度学习 API。它提供了简单的 API,用于从头开始训练深度学习模型、导入现有的 Keras 模型进行推理,以及利用迁移学习将现有的预训练模型调整到您的任务中。

    • Kotlin for Apache Spark在 Kotlin 和 Apache Spark 之间添加了一个缺失的兼容性层。它允许 Kotlin 开发人员使用熟悉的语言功能,例如数据类和 lambda 表达式作为花括号或方法引用中的简单表达式。

    • kotlin-statistics是一个为探索性和生产性统计提供扩展功能的库。它支持基本的数字列表/序列/数组函数(从sumskewness)、切片运算符(例如countBysimpleRegressionBy)、分箱操作、离散 PDF 采样、朴素贝叶斯分类器、聚类、线性回归等等。

    • kmath是一个受NumPy启发的库。该库支持代数结构和运算、类数组结构、数学表达式、直方图、流操作、围绕commons-math和koma的包装器等。

    • krangl是一个受 R 的dplyr和 Python 的pandas启发的库。该库使用函数式 API 提供数据操作功能;它还包括过滤、转换、聚合和重塑表格数据的功能。

    • let-plot是一个用 Kotlin 编写的统计数据绘图库。Lets-Plot 是多平台的,不仅可以与 JVM 一起使用,还可以与 JS 和 Python 一起使用。

    • kravis是另一个受 R 的ggplot启发的用于表格数据可视化的库。

    • londogard-nlp-toolkit是一个库,可在处理自然语言处理(例如词/子词/句子嵌入、词频、停用词、词干提取等)时提供实用程序。

    Java 库

    由于 Kotlin 提供一流的 Java 互操作,您还可以在 Kotlin 代码中使用 Java 库进行数据科学。以下是此类库的一些示例:

    • DeepLearning4J - Java 的深度学习库

    • ND4J - 一个高效的 JVM 矩阵数学库

    • Dex - 基于 Java 的数据可视化工具

    • Smile - 一个全面的机器学习、自然语言处理、线性代数、图形、插值和可视化系统。除了 Java API,Smile 还提供功能性Kotlin API以及 Scala 和 Clojure API。

      • Smile-NLP-kt - 以扩展函数和接口的格式为 Smile 的自然语言处理部分的 Scala 隐式重写的 Kotlin。

    • Apache Commons Math - 适用于 Java 的通用数学、统计和机器学习库

    • NM Dev - 一个涵盖所有经典数学的 Java 数学库。

    • OptaPlanner - 优化规划问题的求解器实用程序

    • Charts - 正在开发的科学 JavaFX 图表库

    • CoreNLP——自然语言处理工具包

    • Apache Mahout - 用于回归、聚类和推荐的分布式框架

    • Weka - 用于数据挖掘任务的机器学习算法集合

    • Tablesaw - Java 数据框。它包括一个基于 Plot.ly 的可视化库

    如果此列表不能满足您的需求,您可以在Thomas Nield的Kotlin 数据科学资源摘要中找到更多选项。

    用于数据科学的 Kotlin

    

    编辑页面
    最后修改时间:2021 年 11 月 16 日

    本教程是为之前没有使用 Kotlin 的竞争性程序员和之前没有参加过任何竞争性编程活动的 Kotlin 开发者设计的。它假定了相应的编程技能。

    竞争性编程是一项智力运动,参赛者编写程序以在严格的限制范围内解决精确指定的算法问题。问题的范围很广,从任何软件开发人员都可以解决的简单问题,只需很少的代码即可获得正确的解决方案,也可以是需要特殊算法、数据结构和大量实践知识的复杂问题。虽然不是专门为竞争性编程而设计的,但 Kotlin 恰好适合这个领域,将程序员在处理代码时需要编写和阅读的典型样板数量几乎减少到动态类型脚本语言提供的水平,同时具有静态类型语言的工具和性能。

    有关如何为 Kotlin 设置开发环境的信息,请参阅Kotlin/JVM 入门。在竞争性编程中,通常创建一个项目,每个问题的解决方案都写在一个源文件中。

    简单示例:可达数问题

    我们来看一个具体的例子。

    Codeforces Round 555 于 4 月 26 日为第 3 分区举行,这意味着它存在适合任何开发人员尝试的问题。您可以使用此链接阅读问题。集合中最简单的问题是问题 A:可达数。它要求实现问题陈述中描述的简单算法。

    我们将通过创建一个具有任意名称的 Kotlin 源文件来开始解决它。A.kt会做得很好。首先,我们需要实现问题陈述中指定的一个函数:

    让我们以这样的方式表示函数 f(x):我们将 1 添加到 x,然后,虽然结果数字中至少有一个尾随零,但我们删除该零。

    Kotlin 是一种务实且无主见的语言,它支持命令式和函数式编程风格,而不会将开发人员推向任何一种风格。我们可以f使用函数式风格实现该函数,使用尾递归等 Kotlin 特性:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">tailrec</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">removeZeroes</span><span style="color:#999999">(</span>x<span style="color:#9a6e3a">:</span> Int<span style="color:#999999">)</span><span style="color:#9a6e3a">:</span> Int <span style="color:#9a6e3a">=</span><strong><span style="color:#0077aa">if</span></strong> <span style="color:#999999">(</span>x <span style="color:#9a6e3a">%</span> <span style="color:#990055">10</span> <span style="color:#9a6e3a">==</span> <span style="color:#990055">0</span><span style="color:#999999">)</span> <span style="color:#dd4a68">removeZeroes</span><span style="color:#999999">(</span>x <span style="color:#9a6e3a">/</span> <span style="color:#990055">10</span><span style="color:#999999">)</span> <strong><span style="color:#0077aa">else</span></strong> x<strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>x<span style="color:#9a6e3a">:</span> Int<span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">removeZeroes</span><span style="color:#999999">(</span>x <span style="color:#9a6e3a">+</span> <span style="color:#990055">1</span><span style="color:#999999">)</span></code></span></span>
    已复制!

    或者,我们可以f使用传统的while 循环和在 Kotlin 中用var表示的可变变量来编写函数的命令式实现:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>x<span style="color:#9a6e3a">:</span> Int<span style="color:#999999">)</span><span style="color:#9a6e3a">:</span> Int <span style="color:#999999">{</span><strong><span style="color:#0077aa">var</span></strong> cur <span style="color:#9a6e3a">=</span> x <span style="color:#9a6e3a">+</span> <span style="color:#990055">1</span><strong><span style="color:#0077aa">while</span></strong> <span style="color:#999999">(</span>cur <span style="color:#9a6e3a">%</span> <span style="color:#990055">10</span> <span style="color:#9a6e3a">==</span> <span style="color:#990055">0</span><span style="color:#999999">)</span> cur <span style="color:#9a6e3a">/=</span> <span style="color:#990055">10</span><strong><span style="color:#0077aa">return</span></strong> cur
    <span style="color:#999999">}</span></code></span></span>
    已复制!

    由于普遍使用类型推断,Kotlin 中的类型在许多地方都是可选的,但每个声明仍然有一个在编译时已知的定义良好的静态类型。

    现在,剩下的就是编写读取输入的主要函数并实现问题陈述要求的算法的其余部分——计算在重复将函数f应用于n给定的初始数字时产生的不同整数的数量在标准输入中。

    默认情况下,Kotlin 在 JVM 上运行,并提供对丰富高效的集合库的直接访问,其中包含通用集合和数据结构,例如动态大小的数组 ( ArrayList)、基于哈希的映射和集合 ( HashMapHashSet)、基于树的有序映射和集合 ( TreeMapTreeSet) 等。使用整数的散列集来跟踪在应用函数时已经达到的值,f问题解决方案的直接命令式版本可以写成如下所示:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">main</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span><strong><span style="color:#0077aa">var</span></strong> n <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// read integer from the input</span><strong><span style="color:#0077aa">val</span></strong> reached <span style="color:#9a6e3a">=</span> HashSet<span style="color:#9a6e3a"><</span>Int<span style="color:#9a6e3a">></span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// a mutable hash set</span><strong><span style="color:#0077aa">while</span></strong> <span style="color:#999999">(</span>reached<span style="color:#999999">.</span><span style="color:#dd4a68">add</span><span style="color:#999999">(</span>n<span style="color:#999999">)</span><span style="color:#999999">)</span> n <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>n<span style="color:#999999">)</span> <span style="color:#708090">// iterate function f</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span>reached<span style="color:#999999">.</span>size<span style="color:#999999">)</span> <span style="color:#708090">// print answer to the output</span>
    <span style="color:#999999">}</span></code></span></span>
    已复制!

    无需处理竞争性编程中输入格式错误的情况。竞争性编程中总是精确指定输入格式,实际输入不能偏离问题陈述中的输入规范。这就是我们使用 Kotlinreadln()函数的原因。它断言输入字符串存在,否则抛出异常。同样,如果输入字符串不是整数,则String.toInt()函数会引发异常。

    所有在线竞争性编程活动都允许使用预先编写的代码,因此您可以定义自己的实用程序函数库,这些功能库面向竞争性编程,使您的实际解决方案代码更易于阅读和编写。然后,您将使用此代码作为解决方案的模板。例如,您可以定义以下辅助函数来读取竞争性编程中的输入:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">private</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">readInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span>
    <strong><span style="color:#0077aa">private</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">readStr</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toString</span><span style="color:#999999">(</span><span style="color:#999999">)</span>
    <span style="color:#708090">// etc for other types you'd use in your solutions</span></code></span></span>
    已复制!

    请注意这里使用的private 可见性修饰符。虽然可见性修饰符的概念与竞争性编程完全无关,但它允许您基于同一模板放置多个解决方案文件,而不会因同一包中的公共声明冲突而出错。

    函数运算符示例:长数问题

    对于更复杂的问题,Kotlin 广泛的集合函数操作库可以派上用场,以最小化样板并将代码转换为线性的从上到下和从左到右的流畅数据转换管道。例如,问题 B:长数问题需要一个简单的贪婪算法来实现,它可以使用这种风格编写,无需单个可变变量:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">main</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">{</span><span style="color:#708090">// read input</span><strong><span style="color:#0077aa">val</span></strong> n <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span><strong><span style="color:#0077aa">val</span></strong> s <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><strong><span style="color:#0077aa">val</span></strong> fl <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">split</span><span style="color:#999999">(</span><strong><span style="color:#669900">" "</span></strong><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">map</span> <span style="color:#999999">{</span> it<span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">}</span><span style="color:#708090">// define local function f</span><strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>c<span style="color:#9a6e3a">:</span> Char<span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <strong><span style="color:#669900">'0'</span></strong> <span style="color:#9a6e3a">+</span> fl<span style="color:#999999">[</span>c <span style="color:#9a6e3a">-</span> <strong><span style="color:#669900">'1'</span></strong><span style="color:#999999">]</span><span style="color:#708090">// greedily find first and last indices</span><strong><span style="color:#0077aa">val</span></strong> i <span style="color:#9a6e3a">=</span> s<span style="color:#999999">.</span><span style="color:#dd4a68">indexOfFirst</span> <span style="color:#999999">{</span> c <span style="color:#9a6e3a">-></span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>c<span style="color:#999999">)</span> <span style="color:#9a6e3a">></span> c <span style="color:#999999">}</span><span style="color:#999999">.</span><span style="color:#dd4a68">takeIf</span> <span style="color:#999999">{</span> it <span style="color:#9a6e3a">>=</span> <span style="color:#990055">0</span> <span style="color:#999999">}</span> <span style="color:#9a6e3a">?:</span> s<span style="color:#999999">.</span>length<strong><span style="color:#0077aa">val</span></strong> j <span style="color:#9a6e3a">=</span> s<span style="color:#999999">.</span><span style="color:#dd4a68">withIndex</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">indexOfFirst</span> <span style="color:#999999">{</span> <span style="color:#999999">(</span>j<span style="color:#999999">,</span> c<span style="color:#999999">)</span> <span style="color:#9a6e3a">-></span> j <span style="color:#9a6e3a">></span> i <span style="color:#9a6e3a">&&</span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>c<span style="color:#999999">)</span> <span style="color:#9a6e3a"><</span> c <span style="color:#999999">}</span><span style="color:#999999">.</span><span style="color:#dd4a68">takeIf</span> <span style="color:#999999">{</span> it <span style="color:#9a6e3a">>=</span> <span style="color:#990055">0</span> <span style="color:#999999">}</span> <span style="color:#9a6e3a">?:</span> s<span style="color:#999999">.</span>length<span style="color:#708090">// compose and write the answer</span><strong><span style="color:#0077aa">val</span></strong> ans <span style="color:#9a6e3a">=</span>s<span style="color:#999999">.</span><span style="color:#dd4a68">substring</span><span style="color:#999999">(</span><span style="color:#990055">0</span><span style="color:#999999">,</span> i<span style="color:#999999">)</span> <span style="color:#9a6e3a">+</span>s<span style="color:#999999">.</span><span style="color:#dd4a68">substring</span><span style="color:#999999">(</span>i<span style="color:#999999">,</span> j<span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">map</span> <span style="color:#999999">{</span> c <span style="color:#9a6e3a">-></span> <span style="color:#dd4a68">f</span><span style="color:#999999">(</span>c<span style="color:#999999">)</span> <span style="color:#999999">}</span><span style="color:#999999">.</span><span style="color:#dd4a68">joinToString</span><span style="color:#999999">(</span><strong><span style="color:#669900">""</span></strong><span style="color:#999999">)</span> <span style="color:#9a6e3a">+</span>s<span style="color:#999999">.</span><span style="color:#dd4a68">substring</span><span style="color:#999999">(</span>j<span style="color:#999999">)</span><span style="color:#dd4a68">println</span><span style="color:#999999">(</span>ans<span style="color:#999999">)</span>
    <span style="color:#999999">}</span></code></span></span>
    已复制!

    在这段密集的代码中,除了集合转换之外,您还可以看到诸如局部函数和elvis 运算符 等方便的 Kotlin 功能,?:它们允许使用简洁易读的表达式表达诸如“如果值为正则取值或使用长度”之类的习惯用法就像.takeIf { it >= 0 } ?: s.length,但是 Kotlin 可以创建额外的可变变量并以命令式风格表达相同的代码。

    为了使在此类竞争性编程任务中读取输入更简洁,您可以使用以下辅助输入读取函数列表:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">private</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">readInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#708090">// single int</span>
    <strong><span style="color:#0077aa">private</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">readStrings</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">split</span><span style="color:#999999">(</span><strong><span style="color:#669900">" "</span></strong><span style="color:#999999">)</span> <span style="color:#708090">// list of strings</span>
    <strong><span style="color:#0077aa">private</span></strong> <strong><span style="color:#0077aa">fun</span></strong> <span style="color:#dd4a68">readInts</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readStrings</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#dd4a68">map</span> <span style="color:#999999">{</span> it<span style="color:#999999">.</span><span style="color:#dd4a68">toInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#999999">}</span> <span style="color:#708090">// list of ints</span></code></span></span>
    已复制!

    有了这些帮助器,读取输入的代码部分变得更简单,一行一行地严格遵循问题陈述中的输入规范:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><span style="color:#708090">// read input</span>
    <strong><span style="color:#0077aa">val</span></strong> n <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readInt</span><span style="color:#999999">(</span><span style="color:#999999">)</span>
    <strong><span style="color:#0077aa">val</span></strong> s <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readln</span><span style="color:#999999">(</span><span style="color:#999999">)</span>
    <strong><span style="color:#0077aa">val</span></strong> fl <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readInts</span><span style="color:#999999">(</span><span style="color:#999999">)</span></code></span></span>
    已复制!

    请注意,在竞争性编程中,通常为变量赋予比工业编程实践中通常更短的名称,因为代码只编写一次,之后不再支持。然而,这些名称通常仍然是助记符——a对于数组、ij等索引、rc表中的行和列号x以及y坐标等。 为输入数据保留相同的名称更容易,因为它在问题陈述。然而,更复杂的问题需要更多的代码,这导致使用更长的不言自明的变量和函数名称。

    更多提示和技巧

    竞争性编程问题通常有这样的输入:

    输入的第一行包含两个整数nk

    在 Kotlin 中,可以使用以下语句使用整数列表中的解构声明来简洁地解析这一行:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><strong><span style="color:#0077aa">val</span></strong> <span style="color:#999999">(</span>n<span style="color:#999999">,</span> k<span style="color:#999999">)</span> <span style="color:#9a6e3a">=</span> <span style="color:#dd4a68">readInts</span><span style="color:#999999">(</span><span style="color:#999999">)</span></code></span></span>
    已复制!

    使用 JVM 的java.util.Scanner类来解析结构性较差的输入格式可能很有吸引力。Kotlin 旨在与 JVM 库进行良好的互操作,因此它们在 Kotlin 中的使用感觉非常自然。但是,请注意这java.util.Scanner非常慢。事实上,如此缓慢,以至于用它解析 10 个5或更多整数可能不符合典型的 2 秒时间限制,这是一个简单的 Kotlinsplit(" ").map { it.toInt() }可以处理的。

    通过println(...)调用和使用 Kotlin 的字符串模板,在 Kotlin 中编写输出通常很简单。但是,当输出包含 10 5行或更多行时必须小心。发出如此多的println调用太慢了,因为 Kotlin 中的输出会在每行之后自动刷新。从数组或列表中写入多行的更快方法是使用joinToString()函数"\n"作为分隔符,如下所示:

    <span style="background-color:var(--wh-color-backlight-main)"><span style="color:var(--wh-color-text-main)"><code><span style="color:#dd4a68">println</span><span style="color:#999999">(</span>a<span style="color:#999999">.</span><span style="color:#dd4a68">joinToString</span><span style="color:#999999">(</span><strong><span style="color:#669900">"\n"</span></strong><span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#708090">// each element of array/list of a separate line</span></code></span></span>
    已复制!

    学习 Kotlin

    Kotlin 很容易学习,特别是对于那些已经了解 Java 的人。可以在网站的从基本语法开始的参考部分中直接找到对面向软件开发人员的 Kotlin 基本语法的简短介绍。

    IDEA 内置了Java-to-Kotlin 转换器。熟悉Java的人可以使用它来学习相应的Kotlin句法结构,但它并不完美,仍然值得熟悉Kotlin和学习Kotlin习语。

    Kotlin Koans是研究 Kotlin 语法和 Kotlin 标准库 API 的重要资源。

Kotlin 概述【官方】相关推荐

  1. [译] Kotlin Flow 官方 Guide 指南(2021-06-13)翻译

    原文链接:https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/topics/flow.md 文章目录 Flow 是冷流 Flow ...

  2. 《Kotlin极简教程》第1章 Kotlin简介

    第1章 Kotlin简介 最新上架!!!< Kotlin极简教程> 陈光剑 (机械工业出版社) 可直接打开京东,淘宝,当当===> 搜索: Kotlin 极简教程 http://ww ...

  3. 阿里架构师开源《Kotlin入门教程指南》+《高级Kotlin强化实战》

    对于有Java基础的程序员来说,Kotlin是一门非常容易上手的编程语言,也是一门必须掌握的编程语言.Java代码在运行前需要编译生成一种特殊的class文件,然后Java虚拟机会识别并解释这些cla ...

  4. 新手入坑编程语言kotlin开局介绍篇

    Kotlin语言简单概述 前言 Kotlin概述 抓住今天,尽可能少的信赖明天. 喝汤能补 (* ^ ▽ ^ *) 前言 自身技能 (1)已具备计算机的基本知识,如:计算机,程序,编程语言等 Kotl ...

  5. Kotlin极简教程(第一章 Kotlin简介)

    1.1 kotlin简史 科特林岛(Котлин)是一座俄罗斯的岛屿,位于圣彼得堡以西约30公里处,形状狭长,东西长度约14公里,南北宽度约2公里,面积有16平方公里,扼守俄国进入芬兰湾的水道.科特林 ...

  6. 吐血推荐|20 个优秀的免费 Kotlin 学习资源

    根据 Realm Q4 报道,Kotlin 编程语言正在飞速抢占 Java 语言在安卓平台的市场份额.截至目前,全世界已经拥有 20% 的 app 在使用 Kotlin 语言开发.Realm 网站更是 ...

  7. 《 Kotlin极简教程 》陈光剑 编著(机械工业出版社,2017.9)

    <Kotlin极简教程> 点击这里 > 去京东商城购买阅读 点击这里 > 去天猫商城购买阅读 正式预售: < Kotlin极简教程 > image.png imag ...

  8. 用Kotlin在IntelliJ Idea中无法生成 spring-configuration-metadata.json 文件

    为什么80%的码农都做不了架构师?>>>    问题描述 在百度搜索关键词,搜索到了 Stack Overflow 有相关问题 spring-configuration-metada ...

  9. 安卓开发重磅炸弹!程序员福利!《高级Kotlin强化实战学习手册(附Demo)》开放下载!

    前言 自Google宣布将 Kotlin 作为 Android 开发的首选语言 (Kotlin-first),现已有60% 的专业 Android 开发者已经采用了该编程语言.在 Google Pla ...

最新文章

  1. zsh:no matches found 问题解决
  2. 【Kaggle-MNIST之路】CNN结构改进+改进过的损失函数(五)
  3. root域名服务器 gtld服务器_购买阿里云域名和空间服务器实操
  4. python 可视化_python可视化基础
  5. linkedin爬虫_您应该在LinkedIn上关注的8个人
  6. 【转】在C#中使用SQLite
  7. 织梦直接往数据库写入数据
  8. HWPFDocument读取doc,wps文档(含图片读取)
  9. 利用Microsoft.VisualBasic dll来修改系统时间
  10. SqlServer实现split功能
  11. STC学习:振动声光报警器
  12. Vulkan-NCNN 编译
  13. 【验证码识别】OpenCV挑战顶象滑动拼图验证码
  14. html5微信公众号开发,微信开放文档
  15. Minecraft 1.16.5模组开发(三十三) 自定义3D方块
  16. 配置中心—Consul配置管理
  17. ToolBoxFeatureDataZoomOpts:工具箱区域缩放配置项
  18. 锐捷无线AC虚拟化配置-VAC
  19. 分享一个计算机视觉图片或者视频的标注神器
  20. Linux面板体验与推荐 AMH、AppNode、WDAP、宝塔

热门文章

  1. catia零件隐藏显示
  2. centos7搭建代理服务器tinyproxy
  3. python——class类和方法的用法详解
  4. FM/FMM算法笔记
  5. 个人以及企业用户如何选择合适的阿里云服务器?
  6. 大学计算机比赛保送,他是信息奥赛金牌得主,保送清华姚班!初中打游戏经常被老师抓...
  7. 微信小程序人脸识别/采集改进版-支持人脸中心位置校验,人脸图片采集(速度更快),人脸搜索
  8. 韩国电商平台 smelchi 店铺开店 数据批量采集上传
  9. Win10电脑更新提示错误0xc1900403怎么解决?
  10. windows上bug崩溃定位分析(Qt或者VS)