ZetCode-Kotlin-教程-一-

ZetCode Kotlin 教程(一)

原文:ZetCode

协议:CC BY-NC-SA 4.0

Kotlin Hello World 教程

原文: http://zetcode.com/kotlin/helloworld/

Kotlin Hello World 教程展示了如何在 Kotlin 中创建 Hello World 程序。

Kotlin 是在 Java 虚拟机上运行的静态类型的编程语言。

Kotlin 由 JetBrains 创建。 Kotlin 是面向对象的函数式编程语言。 Kotlin 被设计为一种务实,简洁,安全且可互操作的编程语言。

安装 Kotlin 编译器

从官方的 Github 存储库中,我们从发行链接下载 Kotlin。 它包含在 ZIP 存档中。 (Kotlin 内置在 IntelliJ IDEA IDE 中。)

$ unzip kotlin-compiler-1.2.21.zip

我们解压缩档案。

$ mv kotlinc ~/bin/

我们将目录移动到我们选择的目的地。

$ export PATH=$PATH:~/bin/kotlinc/bin/

我们将 Kotlin 编译器的路径添加到.bashrc.profile文件中。

Kotlin Hello World 示例

以下程序将简单消息打印到控制台。

hello.kt

package com.zetcode

fun main(args: Array<String>) {

    println("Hello, World!")
}

Kotlin 源文件的扩展名为.kt。 请注意,在 Kotlin 中,我们不必使用分号。

package com.zetcode

源文件可以以package声明开头。 包用于组织类型。 与 Java 不同,Kotlin 不需要包来匹配目录结构。 但是,这样做是一个好习惯。

fun main(args: Array<String>) {

    println("Hello, World!")
}

main()函数是程序的入口点。 使用fun关键字声明函数。 在 Kotlin 中,我们不必将函数放入类中。 println()函数将消息打印到控制台。 main()函数将字符串数组作为参数。 请注意,在 Kotlin 中,类型后跟在冒号后面的变量名。

编译 Kotlin 程序

我们将从命令行编译并运行程序。

$ kotlinc hello.kt 

使用kotlinc编译器,我们可以编译源代码。

$ ls com/zetcode/
HelloKt.class

编译器在com/zetcode子文件夹中创建HelloKt.class

$ kotlin com.zetcode.HelloKt
Hello, World!

我们使用kotlin工具运行该程序。

打包 Kotlin 程序

接下来,我们将展示如何将 Kotlin 程序打包到 Java JAR 文件中。

$ kotlinc hello.kt -include-runtime -d hello.jar

使用-include-runtime选项,我们将 Kotlin 运行时包含在生成的 JAR 文件中。

$ java -jar hello.jar 
Hello, World!

我们使用java工具运行该程序。

在本教程中,我们在 Kotlin 中创建了一个简单的程序。 该程序是使用命令行工具构建并运行的。 您可能也对相关教程感兴趣: Kotlin 变量教程Kotlin 控制流教程Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin 变量

原文: http://zetcode.com/kotlin/variables/

Kotlin 变量教程展示了如何在 Kotlin 中使用变量。

Kotlin 是在 Java 虚拟机上运行的静态类型的编程语言。 每个表达式的类型在编译时都是已知的。

变量是存储数据的地方。 变量具有名称和数据类型。 数据类型确定可以为变量分配哪些值。 Kotlin 具有以下基本类型:DoubleFloatLongIntShortByte

Kotlin 变量

Kotlin 中有两种类型的变量:只读和可变。 只读变量(或常量)用val声明,并用var可变。

Kotlin 数据类型推断

Kotlin 可以从分配的右侧推断变量的数据类型。 仅当推迟分配时,数据类型才是必需的。

val word = "cloud"
val word: String = "cloud"

数据类型遵循标识符和 Kotlin 中的冒号。

Kotlin 变量示例

下面的示例创建两个变量。

KotlinVariables.kt

package com.zetcode

fun main(args: Array<String>) {

    val word = "influence"
    println(word)

    var word2 = "sunshine"
    println(word2)

    word2 = "rain"
    println(word2)
}

有一个只读变量和一个可变变量。

val word = "influence"

使用val关键字,我们定义了一个只读变量。 其值以后无法在程序中更改。 数据类型为 String,这是从赋值右侧的字符串字面值推断出来的。

var word2 = "sunshine"
println(word2)

word2 = "rain"
println(word2)

使用var关键字,我们定义了一个可变变量。 稍后在程序中修改变量的值。

influence
sunshine
rain

这是程序的输出。

Kotlin 变量延迟赋值

在下面的示例中,我们在声明变量后推迟变量的赋值。

KotlinVariableDeffered.kt

package com.zetcode

fun main(args: Array<String>) {

    val input: String?

    print("Enter something: ")
    input = readLine()

    println(input)
}

该示例从用户读取输入。

val input: String?

我们声明一个String数据类型的变量。 后面的问号告诉 Kotlin 该变量可以为 null。 这次必须显式提供数据类型。

print("Enter something: ")

我们向用户打印提示。

input = readLine()

使用readLine()从用户读取输入。 目前,我们已经为input变量分配了一个值。

Kotlin 属性

在类中创建的变量是属性。 只读变量具有默认访问器和可变变量访问器和变异器。

KotlinProperties.kt

package com.zetcode

class Person {

    var name:String = ""
    var age:Int = 0

    override fun toString(): String {
        return "Person(name='$name', age=$age)"
    }
}

fun main(args: Array<String>) {

    val p1 = Person()
    p1.name = "Peter"
    p1.age = 23

    println(p1)
}

在示例中,我们有一个Person类,具有两个属性:nameage

var name:String = ""
var age:Int = 0

我们有两个可变属性。

override fun toString(): String {
    return "Person(name='$name', age=$age)"
}

我们重写toString()方法以获得Person对象的字符串表示形式。

val p1 = Person()
p1.name = "Peter"
p1.age = 23

创建一个Person对象。 我们设置两个属性。

Person(name='Peter', age=23)

这是输出。

在本教程中,我们使用了 Kotlin 中的变量。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin 运算符教程Kotlin 字符串教程Kotlin 控制流教程Kotlin 数组教程Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin 的运算符

原文: http://zetcode.com/kotlin/operators/

在本教程中,我们将介绍 Kotlin 运算符。 我们展示了如何使用运算符创建表达式。

运算符是特殊符号,表示已执行某个过程。 编程语言的运算符来自数学。 程序员处理数据。 运算符用于处理数据。 操作数是运算符的输入(参数)之一。

表达式是根据操作数和运算符构造的。 表达式的运算符指示将哪些运算应用于操作数。 表达式中运算符的求值顺序由运算符的优先级和关联性确定。

一个运算符通常有一个或两个操作数。 那些仅使用一个操作数的运算符称为一元运算符。 那些使用两个操作数的对象称为二进制运算符。

某些运算符可以在不同的上下文中使用。 例如,+运算符可以在不同的情况下使用:它添加数字,连接字符串或指示数字的符号。 我们说运算符是重载。

Kotlin 标志运算符

有两个符号运算符:+-。 它们用于指示或更改值的符号。

KotlinSignOperatorsEx.kt

package com.zetcode

fun main(args: Array<String>) {

    println(2)
    println(+2)
    println(-2)
}

+-符号指示值的符号。 加号可用于表示我们有一个正数。 可以省略它,并且在大多数情况下可以这样做。

KotlinMinusSignEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val a = 1

    println(-a)
    println(-(-a))
}

减号更改值的符号。

Kotlin 赋值运算符

赋值运算符=将值赋给变量。 变量是值的占位符。 在数学中,=运算符具有不同的含义。 在等式中,=运算符是一个相等运算符。 等式的左边等于右边的等式。

val x = 1

在这里,我们为x变量分配一个数字。

x = x + 1

这个表达式在数学上没有意义,但是在编程中是合法的。 该表达式将x变量加 1。 右边等于 2,并且 2 分配给x

3 = x

此代码行导致语法错误。 我们无法为字面值分配值。

Kotlin 扩展赋值运算子

扩展赋值运算符是由两个运算符组成的速记运算符。 增强的赋值运算符在其他编程语言中也称为复合赋值运算符。

a = a + 3
a += 3

+=复合运算符是这些速记运算符之一。 以上两个表达式相等。 将值 3 添加到变量a中。

Kotlin 扩展分配运算符为:

+=  -=   *=   /=   %=   

下面的示例使用两个复合运算符。

KotlinAugmentedAssignmentOperatorsEx.kt

package com.zetcode

fun main(args: Array<String>) {

    var a = 1
    a = a + 1

    println(a)

    a += 5
    println(a)

    a *= 3
    println(a)
}

我们使用+=*=复合运算符。

var a = 1
a = a + 1

a变量被初始化为 1。 使用非速记符号将值 1 添加到变量。

a += 5

使用+=复合运算符,将 5 加到a变量中。 该语句等于a = a + 5

a *= 3

使用*=运算符,将a乘以 3。该语句等于a = a * 3

2
7
21

这是示例输出。

Kotlin 连接字符串

在 Kotlin 中,+运算符还用于连接字符串。

KotlinConcatenateStringsEx.kt

package com.zetcode

fun main(args: Array<String>) {

    println("Return " + "of " + "the king.")
    println("Return".plus(" of").plus(" the king."))
}

我们将三个字符串连接在一起。

println("Return " + "of " + "the king.")

字符串用+运算符连接。

println("Return".plus(" of").plus(" the king."))

连接字符串的另一种方法是plus()方法。

Kotlin 增减运算符

将值递增或递减一个是编程中的常见任务。 Kotlin 为此有两个方便的运算符:++--

x++
x = x + 1
...
y--
y = y - 1

上面两对表达式的作用相同。

KotlinIncDecEx.kt

package com.zetcode

fun main(args: Array<String>) {

    var x = 6

    x++
    x++

    println(x)

    x--
    println(x)
}

在上面的示例中,我们演示了两个运算符的用法。

int x = 6

x++
x++

x变量初始化为 6。然后将x递增两次。 现在变量等于 8。

x--

我们使用减量运算符。 现在变量等于 7。

Kotlin 算术运算符

下表是 Kotlin 中的算术运算符表。

符号 名称
+ 加法
- 减法
* 乘法
/ 乘法
% 余数

以下示例显示了算术运算。

KotlinArithmeticOperatorsEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val a = 10
    val b = 11
    val c = 12

    val add = a + b + c
    val sb = c - a
    val mult = a * b
    val div = c / 3
    val rem = c % a

    println(add)
    println(sb)
    println(mult)
    println(div)
    println(rem)
}

在前面的示例中,我们使用加法,减法,乘法,除法和余数运算。 这些都是数学所熟悉的。

val rem = c % a

%运算符称为余数或模运算符。 它找到一个数除以另一个的余数。 例如9 % 4,9 模 4 为 1,因为 4 两次进入 9 且余数为 1。

整数除法和浮点除法之间有区别。

KotlinDivisionEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val c = 5 / 2
    println(c)

    val d = 5 / 2.0
    println(d)
}

在前面的示例中,我们将两个数字相除。

val c = 5 / 2

在这段代码中,我们完成了整数除法。 除法运算的返回值为整数。 当我们将两个整数相除时,结果是一个整数。

val d = 5 / 2.0

如果值之一是doublefloat,则执行浮点除法。 在我们的例子中,第二个操作数是双精度数,因此结果是双精度数。

2
2.5

我们看到了程序的结果。

Kotlin 布尔运算符

在 Kotlin 中,我们有三个逻辑运算符。

符号 名称
&& 逻辑与
|| 逻辑或
! 否定

布尔运算符也称为逻辑运算符。

KotlinBooleanExpEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val x = 3
    val y = 8

    println(x == y)
    println(y > x)

    if (y > x) {

        println("y is greater than x")
    }
}

许多表达式导致布尔值。 例如,在条件语句中使用布尔值。

println(x == y)
println(y > x)

关系运算符始终导致布尔值。 这两行分别显示falsetrue

if (y > x) {

    println("y is greater than x")
}

仅在满足括号内的条件时才执行if语句的主体。 y > x返回true,因此消息"y大于x"被打印到终端。

truefalse关键字表示 Kotlin 中的布尔字面值。

KotlinAndOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val a = true && true
    val b = true && false
    val c = false && true
    val d = false && false

    println(a)
    println(b)
    println(c)
    println(d)
}

该代码示例显示了逻辑和(&&)运算符。 仅当两个操作数均为true时,它的评估结果为true

true
false
false
false

只有一个表达式可得出true

如果两个操作数中的任何一个为true,则逻辑或(||)运算符的计算结果为true

KotlinOrOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val a = true || true
    val b = true || false
    val c = false || true
    val d = false || false

    println(a)
    println(b)
    println(c)
    println(d)
}

如果运算符的任一侧为真,则操作的结果为真。

true
true
true
false

四个表达式中的三个表示为true

否定运算符!true设为false,并将false设为false

KotlinNegationEx.kt

package com.zetcode

fun main(args: Array<String>) {

    println(! true)
    println(! false)
    println(! (4 < 3))
}

该示例显示了否定运算符的作用。

false
true
true

这是程序的输出。

Kotlin 比较运算符

比较运算符用于比较值。 这些运算符总是产生布尔值。

符号 含义
< 小于
<= 小于或等于
> 大于
>= 大于或等于
== 等于
!= 不等于

比较运算符也称为关系运算符。

KotlinComparisonOperatorsEx.kt

package com.zetcode

fun main(args: Array<String>) {

    println(3 < 4);
    println(3 == 4);
    println(4 >= 3);
    println(4 != 3);
}

在代码示例中,我们有四个表达式。 这些表达式比较整数值。 每个表达式的结果为truefalse。 在 Kotlin 中,我们使用==比较数字。 (某些语言(例如 Ada,Visual Basic 或 Pascal)使用=比较数字。)

Kotlin 按位运算符

与 Java 不同,Kotlin 中没有按位运算符。 Kotlin 已经命名了执行按位运算的函数。

  • shl(bits) – 有符号左移(Java 的<<
  • shr(bits) – 有符号右移(Java 的>>
  • ushr(bits) – 无符号右移(Java 的>>>
  • and(bits) – 按位与
  • or(bits) – 按位或
  • xor(bits) – 按位异或
  • inv() – 按位反转

这些函数仅适用于IntLong类型。

按位操作在两个数字之间进行逐位比较。 仅当操作数中的两个对应位均为 1 时,位位置的结果才为 1。

      00110
   &  00011
   =  00010

第一个数字是二进制符号 6,第二个数字是 3,结果是 2。

println(6 and 3) // prints 2
println(3 and 6) // prints 2

按位或操作在两个数字之间进行逐位比较。 如果操作数中的任何对应位为 1,则位位置的结果为 1。

     00110
   | 00011
   = 00111

结果为00110或十进制 7。

println(6 or 3) // prints 7
println(3 or 6) // prints 7

Kotlin is运算符

要在运行时检查对象是否符合给定类型,我们可以使用is运算符或其否定形式!is

KotlinIsOperatorEx.kt

package com.zetcode

open class Base
class Derived : Base()

fun main(args: Array<String>) {

    val b = Base()
    val d = Derived()

    println(d is Base)
    println(b is Derived)
    println(d is Any)
}

在示例中,我们有两个类:一个基类和一个从基类派生的类。

println(d is Base)

此行检查变量d是否指向作为Base类实例的类。 由于Derived类继承自Base类,因此它也是Base类的实例。 该行打印正确。

println(b is Derived)

b对象不是Derived类的实例。 该行显示false

println(d is Any) 

每个类都有Any作为超类。 因此,d对象也是Any类的实例。

true
false
true

这是程序的输出。

Kotlin Lambda 运算符

Kotlin 具有 lambda 运算符(->)。 它分隔了 lambda 表达式的参数和主体。

KotlinLambdaOperatorEx.kt

package com.zetcode

import java.util.Arrays

fun main(args: Array<String>) {

    val words = arrayOf("kind", "massive", "atom", "car", "blue")

    Arrays.sort(words) { s1: String, s2: String -> s1.compareTo(s2) }

    println(Arrays.toString(words))
}

在示例中,我们定义了一个字符串数组。 使用Arrays.sort()方法和 lambda 表达式对数组进行排序。

[atom, blue, car, kind, massive]

这是输出。

Kotlin 双冒号运算符

双冒号运算符(::)用于创建类或函数引用。

KotlinDoubleColonOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val c = String::class

    c.supertypes.forEach { e -> println(e) }

    val words = listOf("car", "forest", "Bible")
    println(words.map(String::length))
}

在代码示例中,我们使用双冒号运算符创建对类和函数的引用。

val c = String::class

c.supertypes.forEach { e -> println(e) }

对于双冒号运算符,我们指的是String类。 我们打印其所有祖先。

val words = listOf("car", "forest", "Bible")
println(words.map(String::length))

在这里,我们将length()函数应用于列表的所有单词。

kotlin.Comparable<kotlin.String>
kotlin.CharSequence
java.io.Serializable
kotlin.Any
[3, 6, 5]

这是输出。

Kotlin 范围运算符

Kotlin 范围运算符(..)允许创建值范围。

KotlinRanageOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    for (i in 1..14 step 3) {

        println(i)
    }
}

该示例使用范围运算符在for循环中创建整数序列。

1
4
7
10
13

这是输出。

非空断言运算符

null断言运算符(!!)会将任何值转换为非null类型,并且如果该值为null则引发异常。

KotlinNullAssertionOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

//    val words = listOf("forest", null, "Bible", "sky")
    val words = listOf("forest", "Bible", "sky")

    var nOfChars: Int = 0

    for (word in words) {

        val n = word!!.length
        nOfChars += n
    }

    println("There are ${nOfChars} characters in the list")
}

该示例计算单词列表中的字符数。 如果列表包含空值,则抛出KotlinNullPointerException

Kotlin Elvis 运算符

Elvis 运算符?:如果不为 null,则返回其第一个表达式,否则返回第二个表达式。

KotlinElvisOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("forest", null, "Bible", "sky")

    for (word in words) {

        val n = word?.length ?: 0

        println("${word} has ${n} letters")
    }
}

在示例中,我们使用 Elvis 运算符检查列表中的空值。

val n = word?.length ?: 0

如果变量word包含 null,则?:返回 0。

forest has 6 letters
null has 0 letters
Bible has 5 letters
sky has 3 letters

这是输出。

Kotlin 空安全运算符

Kotlin 的null安全操作符?.提供了安全的方法调用-仅当对象不为null时才调用方法。

KotlinNullSafetyOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("forest", null, "Bible", "sky")

    for (word in words) {

        println(word?.toUpperCase())
}

在示例中,我们将字符串转换为大写; 我们使用null安全运算符。 对于null值,不调用该方法。

FOREST
null
BIBLE
SKY

这是输出。

Kotlin 索引访问运算符

Kotlin 索引访问运算符用于从数组获取值。

KotlinIndexAccessOperatorEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = arrayOf(3, 2, 1, 4, 5, 6, 7)

    val v1 = nums[0]
    val v2 = nums[3]

    println(v1)
    println(v2)
}

在示例中,我们使用[]运算符从数组中检索两个值。

Kotlin 引用相等运算符

Kotlin 区分结构相等和引用相等。 结构相等运算符(==)检查两个对象是否具有相同的内容。 引用相等运算符(===)检查变量是否指向内存中的同一对象。

KotlinreferentialEqualityOperatorEx.kt

package com.zetcode

data class Item(var name: String, var color: String)

fun main(args: Array<String>) {    

    val i1 = Item("coin", "brown")
    val i2 = i1

    println("Output: ${i1 == i2}")
    println("Output: ${i1 === i2}")

    val i3 = Item("coin", "brown")
    val i4 = Item("coin", "brown")

    println("Output: ${i3 == i4}")
    println("Output: ${i3 === i4}")
}

该示例演示了=====运算符之间的区别。

Output: true
Output: true
Output: true
Output: false

这是输出。

Kotlin 运算符优先级

运算符优先级告诉我们首先评估哪个运算符。 优先级对于避免表达式中的歧义是必要的。

以下表达式 28 或 40 的结果是什么?

3 + 5 * 5

像数学中一样,乘法运算符的优先级高于加法运算符。 结果是 28。

(3 + 5) * 5

要更改评估的顺序,可以使用括号。 括号内的表达式始终首先被求值。 上面的表达式的结果是 40。

KotlinOperatorPrecedenceEx.kt

package com.zetcode

fun main(args: Array<String>) {

    println(3 + 5 * 5)
    println((3 + 5) * 5)

    println(!true or true)
    println(!(true or true))
}

在此代码示例中,我们显示一些表达式。 每个表达式的结果取决于优先级。

println(3 + 5 * 5)

该行打印 28。乘法运算符的优先级高于加法。 首先,计算5 * 5的乘积,然后加 3。

println((3 + 5) * 5)

可以通过使用方括号来更改表达式的求值。 在这种情况下,将评估3 + 5,然后将该值乘以 5。此行显示 40。

println(!true or true)

在这种情况下,求反运算符的优先级高于按位或。 首先,将初始true值取反为false,然后|运算符将falsetrue组合在一起,最后给出true

28
40
true
false

这是示例输出。

关联规则

有时,优先级不能令人满意地确定表达式的结果。 还有另一个规则称为关联性。 运算符的关联性决定了具有相同优先级的运算符的评估顺序。

9 / 3 * 3

此表达式的结果是 9 还是 1? 乘法,删除和模运算符从左到右关联。 因此,该表达式的计算方式为:(9 / 3) * 3,结果为 9。

算术运算符,布尔运算符和关系运算符从左到右关联。 三元运算符,递增,递减,一元正负,取反,按位不,类型强制转换,对象创建运算符从右到左关联。

KotlinAssociativityRuleEx.kt

package com.zetcode

fun main(args: Array<String>) {

    var j = 0

    j *= 3 + 1

    println(j)
}

在示例中,我们的关联规则确定表达式的结果。

var j = 0

j *= 3 + 1

增强的赋值运算符从右到左关联。 我们可能期望结果为 1。但是实际结果为 0。由于有关联性。 首先评估右边的表达式,然后应用复合赋值运算符。

计算素数

在下面的示例中,我们将计算素数。

KotlinPrimeNumbersEx.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
            14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28)

    print("Prime numbers: ")

    for (num in nums) {

        if (num == 0 || num == 1) {
            continue
        }

        if (num == 2 || num == 3) {

            print(num.toString() + " ")
            continue
        }

        var i = Math.sqrt(num.toDouble()).toInt()

        var isPrime = true

        while (i > 1) {

            if (num % i == 0) {

                isPrime = false
            }

            i--
        }

        if (isPrime) {

            print(num.toString() + " ")
        }
    }

    print('\n')
}

在上面的示例中,我们处理了几个运算符。 质数(或质数)是一个自然数,它具有两个截然不同的自然数除数:1 和它本身。 我们选择一个数字并将其除以 1 到所选数字的数字。 实际上,我们不必尝试所有较小的数字。 我们可以将数字除以所选数字的平方根。 该公式将起作用。 我们使用余数除法运算符。

val nums = intArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28)

我们将从这些数字计算素数。

if (num == 0 || num == 1) {
    continue
}

值 0 和 1 不被视为素数。

if (num == 2 || num == 3) {

    print(num.toString() + " ")
    continue
}

我们跳过 2 和 3 的计算。它们是质数。 请注意等式和条件或运算符的用法。 ==的优先级高于||运算符。 因此,我们不需要使用括号。

var i = Math.sqrt(num.toDouble()).toInt()

如果我们仅尝试小于所讨论数字的平方根的数字,那么我们可以。

while (i > 1) { 
    ...
    i--;
}

这是一个while循环。 i是计算出的数字的平方根。 我们使用减量运算符将每个循环周期的i减 1。 当i小于 1 时,我们终止循环。 例如,我们有 9。9 的平方根是 3。我们将 9 的数字除以 3 和 2。这对于我们的计算就足够了。

if (num % i == 0) {

    isPrime = false
}

如果余数除法运算符针对任何i值返回 0,则说明该数字不是质数。

在本教程中,我们介绍了 Kotlin 运算符。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin 变量教程Kotlin 字符串教程Kotlin 控制流教程Kotlin 数组教程

Kotlin when表达式

原文: http://zetcode.com/kotlin/when/

Kotlin when表达式教程展示了如何在 Kotlin 中使用when表达式。 when表达式替换了 C 语言族中已知的switch语句。

Kotlin 是在 Java 虚拟机上运行的静态类型的编程语言。

Kotlin 在将其参数依次与所有分支匹配之前,直到满足某个分支条件为止。 它既可以用作表达式也可以用作语句。 如果将其用作表达式,则满足的分支的值将成为整个表达式的值。

Kotlin 的简单例子

以下是一个简单的示例,该示例使用带有星期几的when表达式。

day_of_week.kt

package com.zetcode

fun main() {

    val dayOfWeek = 3

    when (dayOfWeek) {
        1 -> println("monday")
        2 -> println("tuesday")
        3 -> println("wednesday")
        4 -> println("thursday")
        5 -> println("friday")
        6 -> println("saturday")
        7 -> println("sunday")
        else -> println("invalid day")
    }
}

在该示例中,我们基于整数值打印星期几。 依次测试七个不同的分支。 如果满足其中之一,则其余的将被跳过。 如果都不满足,则执行else分支。

Kotlin when将值分组

可以使用逗号运算符在分支中将值分组。

day_of_week2.kt

package com.zetcode

fun main() {

    val dayOfWeek = 5

    when (dayOfWeek){
        1,2,3,4,5 -> println("weekday")
        6,7 -> println("weekend")
        else -> println("wrong value")
    }
}

在示例中,我们将值分组以形成两个分支:工作日和周末。

Kotlin when表达式示例

Kotlin when可以用作表达式。 返回满意分支的值。

when_expression.kt

package com.zetcode

import java.time.DayOfWeek
import java.time.LocalDate

fun main() {

    val dayOfWeek: DayOfWeek = LocalDate.now().dayOfWeek

    val msg:String = when (dayOfWeek) {
        DayOfWeek.MONDAY -> "It is monday"
        DayOfWeek.TUESDAY -> "It is tuesday"
        DayOfWeek.WEDNESDAY -> "It is tuesday"
        DayOfWeek.THURSDAY -> "It is tuesday"
        DayOfWeek.FRIDAY -> "It is tuesday"
        DayOfWeek.SATURDAY -> "It is tuesday"
        DayOfWeek.SUNDAY -> "It is tuesday"
        else -> "Invalid day of week"
    }

    println(msg)
}

我们确定当前工作日。 来自匹配分支的字符串被分配给msg变量,该变量随后被打印到控制台。

Kotlin when范围

我们可以在when分支中测试值的范围。 (这也可以通过集合来完成。)

age_groups.kt

package com.zetcode

fun main() {

    val age = 40

    when (age) {
        in 0..14 -> println("children")
        in 15..24 -> println("youth")
        in 25..64 -> println("adults")
        in 65..120 -> println("seniors")
        in 120..130 -> println("unlikely age")
        else -> println("wrong age value")
    }
}

我们有一个年龄变量。 我们使用 Kotlin 范围将值分配给年龄组。

Kotlin when枚举

Kotlin 表达式可与枚举一起使用时。

when_enums.kt

package com.zetcode

enum class Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

fun main() {

    val season = Season.SUMMER

    when (season) {

        Season.SPRING -> println("It is spring")
        Season.SUMMER -> println("It is summer")
        Season.AUTUMN -> println("It is autumn")
        Season.WINTER -> println("It is winter")
    }
}

我们有一个Season枚举。 我们将枚举作为when表达式的参数传递。

Kotlin when不带参数

Kotlin when可以不带参数使用表达式。

random_val.kt

package com.zetcode

import java.util.Random

fun main() {

    val r:Int = Random().nextInt(10) - 5

    when {
        r < 0 -> println("negative value")
        r == 0 -> println("zero")
        r > 0 -> println("positive value")
    }
}

在示例中,我们生成一个随机值。 我们使用when表达式测试该值,而不将其作为参数放在圆括号中。

Kotlin when类型

我们可以使用is运算符检查类型。

when_types.kt

package com.zetcode

import javax.lang.model.type.ArrayType

fun main() {

    val variable: Any = 23

    when (variable) {

        is Int -> println("It is an integer")
        is String -> println("It is a string")
        is ArrayType -> println("It is an array")
    }
}

在示例中,我们在when表达式中检查变量的类型。

在本教程中,我们介绍了 Kotlin 中的when表达式。 您可能也对相关教程感兴趣: Kotlin 控制流教程Kotlin 范围教程或列出所有 Kotlin 教程

Kotlin 数组

原文: http://zetcode.com/kotlin/arrays/

Kotlin 数组教程展示了如何在 Kotlin 中使用数组。

数组是固定数量的值的集合。 数组项称为数组的元素。 每个元素都可以由索引引用。 数组从零开始。

使用诸如arrayOf()intArrayOf()之类的函数或诸如IntArrayFloatArray之类的类创建 Kotlin 数组。

Kotlin 数组初始化

在第一个示例中,我们展示了如何在 Kotlin 中初始化数组。

KotlinArrayInit.kt

package com.zetcode

import java.util.Arrays

fun main() {

    val nums = arrayOf(1, 2, 3, 4, 5)
    println(Arrays.toString(nums))

    val nums2 = (3..12).toList().toTypedArray()
    println(Arrays.toString(nums2))

    val nums3 = IntArray(5, { i -> i * 2 + 3})
    println(Arrays.toString(nums3))
}

该示例创建三个数组。

val nums = arrayOf(1, 2, 3, 4, 5)

使用arrayOf()函数创建一个数组。

println(Arrays.toString(nums))

我们使用Arrays' toString()方法来打印数组的内容。

val nums2 = (3..12).toList().toTypedArray()

在这一行中,我们根据一系列数字创建一个数组。

val nums3 = IntArray(5, { i -> i * 2 + 3})

该行使用IntArray创建一个数组。 它以元素数量和工厂功能为参数。

[1, 2, 3, 4, 5]
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
[3, 5, 7, 9, 11]

这是输出。

Kotlin 数组索引

下一个示例显示 Kotlin 中的数组索引操作。

KotlinArrayIndexing.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(1, 2, 3, 4, 5)

    println(nums[2])

    nums[0] = 11
    println(nums[0])
}

我们使用索引操作来获取和修改数组值。

println(nums[2])

我们用索引 2 打印该值,即数组中的第三个元素。 数组值的索引添加在一对方括号之间。

Kotlin 数组基本操作

以下示例介绍了 Kotlin 数组的一些基本操作。

KotlinArrayBasicOperations.kt

package com.zetcode

import java.util.Arrays

fun main() {

    val nums = arrayOf(1, 2, 3, 4, 5)
    println(nums.get(0))

    nums.set(0, 0)
    println(Arrays.toString(nums))

    val nums2 = nums.plus(1)
    println(Arrays.toString(nums2))

    val slice = nums.sliceArray(1..3)
    println(Arrays.toString(slice))

    println(nums.first())
    println(nums.last())
    println(nums.indexOf(5))
}

在该示例中,我们检索和修改数组元素,创建切片,并获取元素的索引。

println(nums.get(0))

我们使用get()函数获得索引为 0 的元素。

nums.set(0, 0)

set()方法将指定索引处的数组元素设置为指定值。

val nums2 = nums.plus(1)

我们向数组添加一个新元素,创建一个新数组。 (请记住,数组是固定大小的;因此,创建了一个新的数组)。

val slice = nums.sliceArray(1..3)

使用sliceArray()方法,我们从数组中创建一个切片。 索引都包含在内。

println(nums.first())
println(nums.last())

我们得到数组的第一个和最后一个元素。

println(nums.indexOf(5))

我们获得元素 5 首次出现的索引。

1
[0, 2, 3, 4, 5]
[0, 2, 3, 4, 5, 1]
[2, 3, 4]
0
5
4

这是输出。

Kotlin 数组内置方法

在下面的示例中,我们使用一些内置的数组方法。

KotlinArrayBuiltins.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(1, 2, 3, 4, 5)

    val avg = nums.average()
    println("The average is $avg")

    val nOfValues = nums.count()
    println("There are $nOfValues elements")

    val sumOfValues = nums.sum()
    println("The sum of values is $sumOfValues")

    val maxValue = nums.max()
    println("The maximum is $maxValue")

    val minValue = nums.min()
    println("The minimum is $minValue")
}

该示例计算数组的平均值,总和,最大值,最小值和大小。

val avg = nums.average()

average()函数计算数组值的平均值。

val nOfValues = nums.count()

元素数由count()确定。

The average is 3.0
There are 5 elements
The sum of values is 15
The maximum is 5
The minimum is 1

这是示例的输出。

Kotlin 数组计数

count()方法对数组中的元素进行计数。

KotlinArrayCount.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(2, 3, 4, 5, 6, 7)

    println("There are ${nums.count()} elements in the array")

    val nOfEvens = nums.count { it % 2 == 0 }

    println("There are $nOfEvens even values in the array")
}

该示例计算数组中值的总数和偶数的数量。

There are 6 elements in the array
There are 3 even values in the array

这是输出。

Kotlin 数组遍历

在下一个示例中,我们遍历 Kotlin 数组。

KotlinTraverseArrays.kt

package com.zetcode

fun main() {

    val nums = arrayOf(1, 2, 3, 4, 5, 6, 7)

    nums.forEach({ e -> print("$e ") })

    println()

    nums.forEachIndexed({i, e -> println("nums[$i] = $e")})

    for (e in nums) {
        print("$e ")
    }

    println()

    val it: Iterator<Int> = nums.iterator()

    while (it.hasNext()) {

        val e = it.next()
        print("$e ")
    }
}

该示例使用四种不同的遍历方式遍历数组。

nums.forEach({ e -> print("$e ") })

我们使用forEach()遍历数组。 此方法对数组的每个元素应用操作。 在我们的情况下将其打印出来。

nums.forEachIndexed({i, e -> println("nums[$i] = $e")})

forEachIndexed()在每个元素上执行给定的操作,为元素提供顺序索引。

for (e in nums) {
    print("$e ")
}

我们在for循环中遍历数组。

val it: Iterator<Int> = nums.iterator()

while (it.hasNext()) {

    val e = it.next()
    print("$e ")
}

最后,我们使用迭代器和while循环遍历数组。

1 2 3 4 5 6 7 
nums[0] = 1
nums[1] = 2
nums[2] = 3
nums[3] = 4
nums[4] = 5
nums[5] = 6
nums[6] = 7
1 2 3 4 5 6 7 
1 2 3 4 5 6 7 

这是示例的输出。

Kotlin 数组排序

我们展示了如何对 Kotlin 数组进行排序。

KotlinArraySort.kt

package com.zetcode

fun main() {

    val nums = arrayOf(7, 3, 3, 4, 5, 9, 1)

    val sortedNums = nums.sortedArray()
    println(Arrays.toString(sortedNums))

    val sortedNumsDesc = nums.sortedArrayDescending()
    println(Arrays.toString(sortedNumsDesc))
}

该示例对数组进行排序,其中sortedArray()为升序,sortedArrayDescending()为降序。 该方法创建新的排序数组。

[1, 3, 3, 4, 5, 7, 9]
[9, 7, 5, 4, 3, 3, 1]

这是示例的输出。

Kotlin 二维数组

在 Kotlin 中,我们可以创建二维数组。

KotlinArrayTwoDim.kt

package com.zetcode

fun main() {

    val array = arrayOf(intArrayOf(1, 2),
            intArrayOf(3, 4),
            intArrayOf(5, 6, 7))

    println(Arrays.deepToString(array))
}

该示例通过将intArrayOf()函数调用嵌套到arrayOf()函数中来创建二维数组。

[[1, 2], [3, 4], [5, 6, 7]]

这是输出。

Kotlin 数组过滤

使用filter()方法,我们可以过滤数组中的数据。

KotlinArrayFilter.kt

package com.zetcode

fun main() {

    val nums = arrayOf(1, -2, 3, 4, -5, 7)

    nums.filter { e -> e > 0 }.forEach { e -> print("$e ") }
}

本示例创建一个正负整数数组。 filter()方法仅用于拾取正值。

1 3 4 7 

这是输出。

Kotlin 数组查找元素

我们可以使用find()findLast()找到元素。

KotlinArrayFind.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

    val firstEven = nums.find { it % 2 == 0 }
    println("The first even value is: $firstEven")

    val lastEven = nums.findLast { it % 2 == 0 }
    println("The last even value is: $lastEven")
}

该示例在数组中查找第一个和最后一个偶数值。

The first even value is: 2
The last even value is: 8

这是输出。

Kotlin 数组归约

归约是将数组值聚合为单个值的终端操作。 reduce()方法对累加器和数组中的每个元素(从左到右)应用一个函数,以将其减小为单个值。

KotlinArrayReduce.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(2, 3, 4, 5, 6, 7)

    val total = nums.reduce { product, next -> product * next }

    println(total)
}

我们使用reduce()方法从数组元素计算乘积。

val total = nums.reduce { product, next -> product * next }

product是累加器,next是数组中的下一个值。

5040

这是输出。

Kotlin 数组all()

如果所有元素都匹配给定谓词,则all()方法返回true

KotlinArrayAll.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

    val hasAllEvens = nums.all { it % 2 == 0 }

    if (hasAllEvens) {

        println("The array contains only even values")
    } else {

        println("The array contains odd values")
    }
}

该示例检查数组元素是否全部为偶数。

The array contains odd values

该数组包含一些奇数值。

Kotlin 数组any()

如果至少一个元素与给定谓词匹配,则any()方法返回true

KotlinArrayAny.kt

package com.zetcode

fun main() {

    val nums = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)

    val hasEvenVals = nums.any { it % 2 == 0 }

    if (hasEvenVals) {

        println("The array contains even values")
    } else {

        println("The array does contain even values")
    }
}

该示例检查数组元素是否包含任何偶数值。

The array contains even values

这是输出。

在本教程中,我们介绍了 Kotlin 数组。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin 设置教程Kotlin 映射教程或列出所有 Kotlin 教程 ]。

Kotlin 范围

原文: http://zetcode.com/kotlin/ranges/

Kotlin 范围教程显示了如何在 Kotlin 中使用范围。

范围是定义的下限和上限之间的一系列值。

使用..运算符或rangeTo()downTo()函数创建 Kotlin 范围。 Kotlin 范围默认为包含范围; 也就是说,1..3创建一个 1、2、3 值的范围。 两个值之间的距离由步长定义。 默认步骤是 1。

Kotlin 创建范围

以下示例显示了如何在 Kotlin 中创建简单范围。

KotlinRangeCreate.kt

package com.zetcode

fun main() {

    for (i in 1..30)
        print("$i ")

    println()

    for (i in 30 downTo 1)
        print("$i ")

    println()

    for (i in 1.rangeTo(30))
        print("$i ")

    println()

    for (i in 30.downTo(1))
        print("$i ")

    println()
}

该示例创建四个值范围。

for (i in 1..30)
    print("$i ")

1..30创建从 1 到 30 的一系列值,包括边界。 我们使用for循环遍历该范围。

for (i in 30 downTo 1)
    print("$i ")

使用downTo关键字,我们创建了一系列从 30 降到 1 的值。

for (i in 1.rangeTo(30))
    print("$i ")

rangeTo()函数在定义的边界之间创建一个值范围; 它等效于..运算符。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 
30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 

这是输出。

Kotlin 的字符范围

我们可以在 Kotlin 中创建一系列字符。

KotlinRangeChars.kt

package com.zetcode

fun main() {

    for (c in 'a'..'k')
        print("$c ")

    println()

    for (c in 'k' downTo 'a')
        print("$c ")
}

本示例创建两个字母范围的升序和降序。

for (c in 'a'..'k')
    print("$c ")

我们创建并打印"a""k"个字符。

for (c in 'k' downTo 'a')
    print("$c ")

我们创建并将"k"打印为"a"字符。

a b c d e f g h i j k 
k j i h g f e d c b a

这是输出。

Kotlin 范围forEach()

我们可以使用forEach()函数遍历值的范围。

KotlinRangeForEach.kt

package com.zetcode

fun main() {

    (1..5).forEach(::println)

    (1..5).reversed().forEach { e -> print("$e ") }
}

该示例使用forEach()函数遍历范围。

(1..5).forEach(::println)

使用forEach()函数,我们可以打印1..5范围内的所有值。

(1..5).reversed().forEach { e -> print("$e ") }

在这一行中,我们使用reversed()反转范围,并使用forEach()遍历该范围。

1
2
3
4
5
5 4 3 2 1 

这是输出。

Kotlin 范围迭代器

我们可以使用经典的迭代器在 Kotlin 中循环遍历。

KotlinRangeIterator.kt

package com.zetcode

fun main() {

    val chars = ('a'..'f')
    val it = chars.iterator()

    while (it.hasNext()) {

        val e = it.next()
        println(e)
    }
}

该示例使用迭代器遍历一系列字符。

val chars = ('a'..'f')
val it = chars.iterator()

我们创建一个字符范围和一个从该范围开始的迭代器。

while (it.hasNext()) {

    val e = it.next()
    println(e)
}

while循环中,我们遍历范围的元素。 hasNext()方法检查范围内是否有下一个元素,next()方法返回范围内的下一个元素。

a
b
c
d
e
f

这是输出。

Kotlin 范围step

使用step关键字,我们可以定义范围值之间的步长。

KotlinRangeStep.kt

package com.zetcode

fun main() {

    for (e in 1..20 step 2) {
        print("$e ")
    }

    println()

    for (e in 1..20 step 5) {
        print("$e ")
    }

    println()

    println((1..10 step 2).last)
    println((1..10 step 3).first)
    println((1..10 step 4).step)

    println()
}

该示例显示了如何在 Kotlin 范围内使用step

for (e in 1..20 step 2) {
    print("$e ")
}

for循环遍历范围的值。 范围具有步骤 2。

println((1..10 step 2).last)
println((1..10 step 3).first)
println((1..10 step 4).step)

Kotlin 范围包含lastfirststep属性,这些属性返回最后一个,第一个值和步骤。

1 3 5 7 9 11 13 15 17 19 
1 6 11 16 
9
1
4

这是输出。

Kotlin 范围过滤器,归约,映射

Kotlin 范围包含过滤,归约和映射操作。

KotlinRangeFilterReduceMap.kt

package com.zetcode

fun main() {

    val rnums = (1..15)

    println(rnums)

    val r = rnums.filter { e -> e % 2 == 0 }
    println(r)

    val r2 = rnums.reduce { total, next -> next * 2 - 1 }
    println(r2)

    var r3 = rnums.map { e -> e * 5 }
    println(r3)
}

该示例在范围上应用过滤,归约和映射。

val r = rnums.filter { e -> e % 2 == 0 }

使用filter()函数,我们可以滤除偶数。 偶数可以被二除而无余数。 该操作返回值列表。

val r2 = rnums.reduce { total, next -> next * 2 - 1 }

归约运算将给定表达式应用于每个范围元素以产生单个值。

var r3 = rnums.map { e -> e * 5 }

映射操作将给定操作应用于每个元素。 映射返回修改值的列表。

1..15
[2, 4, 6, 8, 10, 12, 14]
29
[5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75]

这是输出。

Kotlin 范围最小,最大,总和,平均值

Kotlin 范围包含预定义的归约运算,包括min()max()sum()average()

KotlinRangeMinMaxSumAvg.kt

package com.zetcode

fun main() {

    val r = (1..10)

    println(r.min())
    println(r.max())
    println(r.sum())    
    println(r.average())
}

该示例打印范围为1..10的值的最小值,最大值,总和和平均值。

1
10
55
5.5

这是输出。

在本教程中,我们涵盖了 Kotlin 范围。 您可能也对相关教程感兴趣: Kotlin 正则表达式Kotlin 变量教程Kotlin 字符串教程Kotlin 控制流, 或列出所有 Kotlin 教程

Kotlin 贪食蛇

原文: http://zetcode.com/kotlin/snake/

Kotlin 贪食蛇游戏教程展示了如何使用 Swing 在 Kotlin 中创建蛇游戏。

源代码和图像可从作者的 Github Kotlin-Snake-Game 存储库中获得。

贪食蛇

贪食蛇是较旧的经典视频游戏。 它最初是在 70 年代后期创建的。 后来它被带到 PC 上。 在这个游戏中,玩家控制蛇。 游戏的目的是尽可能多地吃苹果。 当蛇吃了一个苹果时,它的身体就长了。 蛇必须避开墙壁和自己的身体。 该游戏有时称为 Nibbles 。

Swing

Swing 是 Java 编程语言的主要 GUI 工具包。 它是 JFC(Java 基础类)的一部分,JFC 是用于为 Java 程序提供图形用户界面的 API。

Kotlin 贪食蛇游戏

蛇的每个关节的大小为 10 像素。 蛇由光标键控制。 最初,蛇具有三个关节。 如果游戏结束,则在面板中间显示"Game Over"消息。

Board.kt

package com.zetcode

import java.awt.*
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent

import javax.swing.ImageIcon
import javax.swing.JPanel
import javax.swing.Timer

class Board : JPanel(), ActionListener {

    private val boardWidth = 300
    private val boardHeight = 300
    private val dotSize = 10
    private val allDots = 900
    private val randPos = 29
    private val delay = 140

    private val x = IntArray(allDots)
    private val y = IntArray(allDots)

    private var nOfDots: Int = 0
    private var appleX: Int = 0
    private var appleY: Int = 0

    private var leftDirection = false
    private var rightDirection = true
    private var upDirection = false
    private var downDirection = false
    private var inGame = true

    private var timer: Timer? = null
    private var ball: Image? = null
    private var apple: Image? = null
    private var head: Image? = null

    init {

        addKeyListener(TAdapter())
        background = Color.black
        isFocusable = true

        preferredSize = Dimension(boardWidth, boardHeight)
        loadImages()
        initGame()
    }

    private fun loadImages() {

        val iid = ImageIcon("src/main/resources/dot.png")
        ball = iid.image

        val iia = ImageIcon("src/main/resources/apple.png")
        apple = iia.image

        val iih = ImageIcon("src/main/resources/head.png")
        head = iih.image
    }

    private fun initGame() {

        nOfDots = 3

        for (z in 0 until nOfDots) {
            x[z] = 50 - z * 10
            y[z] = 50
        }

        locateApple()

        timer = Timer(delay, this)
        timer!!.start()
    }

    public override fun paintComponent(g: Graphics) {
        super.paintComponent(g)

        doDrawing(g)
    }

    private fun doDrawing(g: Graphics) {

        if (inGame) {

            g.drawImage(apple, appleX, appleY, this)

            for (z in 0 until nOfDots) {
                if (z == 0) {
                    g.drawImage(head, x[z], y[z], this)
                } else {
                    g.drawImage(ball, x[z], y[z], this)
                }
            }

            Toolkit.getDefaultToolkit().sync()

        } else {

            gameOver(g)
        }
    }

    private fun gameOver(g: Graphics) {

        val msg = "Game Over"
        val small = Font("Helvetica", Font.BOLD, 14)
        val fontMetrics = getFontMetrics(small)

        val rh = RenderingHints(
                RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON)

        rh[RenderingHints.KEY_RENDERING] = RenderingHints.VALUE_RENDER_QUALITY

        (g as Graphics2D).setRenderingHints(rh)

        g.color = Color.white
        g.font = small
        g.drawString(msg, (boardWidth - fontMetrics.stringWidth(msg)) / 2, 
            boardHeight / 2)
    }

    private fun checkApple() {

        if (x[0] == appleX && y[0] == appleY) {

            nOfDots++
            locateApple()
        }
    }

    private fun move() {

        for (z in nOfDots downTo 1) {
            x[z] = x[z - 1]
            y[z] = y[z - 1]
        }

        if (leftDirection) {
            x[0] -= dotSize
        }

        if (rightDirection) {
            x[0] += dotSize
        }

        if (upDirection) {
            y[0] -= dotSize
        }

        if (downDirection) {
            y[0] += dotSize
        }
    }

    private fun checkCollision() {

        for (z in nOfDots downTo 1) {

            if (z > 4 && x[0] == x[z] && y[0] == y[z]) {
                inGame = false
            }
        }

        if (y[0] >= boardHeight) {
            inGame = false
        }

        if (y[0] < 0) {
            inGame = false
        }

        if (x[0] >= boardWidth) {
            inGame = false
        }

        if (x[0] < 0) {
            inGame = false
        }

        if (!inGame) {
            timer!!.stop()
        }
    }

    private fun locateApple() {

        var r = (Math.random() * randPos).toInt()
        appleX = r * dotSize

        r = (Math.random() * randPos).toInt()
        appleY = r * dotSize
    }

    override fun actionPerformed(e: ActionEvent) {

        if (inGame) {

            checkApple()
            checkCollision()
            move()
        }

        repaint()
    }

    private inner class TAdapter : KeyAdapter() {

        override fun keyPressed(e: KeyEvent?) {

            val key = e!!.keyCode

            if (key == KeyEvent.VK_LEFT && !rightDirection) {
                leftDirection = true
                upDirection = false
                downDirection = false
            }

            if (key == KeyEvent.VK_RIGHT && !leftDirection) {
                rightDirection = true
                upDirection = false
                downDirection = false
            }

            if (key == KeyEvent.VK_UP && !downDirection) {
                upDirection = true
                rightDirection = false
                leftDirection = false
            }

            if (key == KeyEvent.VK_DOWN && !upDirection) {
                downDirection = true
                rightDirection = false
                leftDirection = false
            }
        }
    }
}

首先,我们将定义游戏中使用的属性。

private val boardWidth = 300
private val boardHeight = 300
private val dotSize = 10
private val allDots = 900
private val randPos = 29
private val delay = 140

boardWidthboardHeight属性确定电路板的大小。 dotSize是苹果的大小和蛇的点。 allDots属性定义了板上可能的最大点数(900 = (300 * 300) / (10 * 10))。 randPos属性用于计算苹果的随机位置。 delay属性确定游戏的速度。

private val x = IntArray(allDots)
private val y = IntArray(allDots)

这两个数组存储蛇的所有关节的xy坐标。

private fun loadImages() {

    val iid = ImageIcon("src/main/resources/dot.png")
    ball = iid.image

    val iia = ImageIcon("src/main/resources/apple.png")
    apple = iia.image

    val iih = ImageIcon("src/main/resources/head.png")
    head = iih.image
}

loadImages()方法中,我们获得了游戏的图像。 ImageIcon类用于显示 PNG 图像。

private fun initGame() {

    nOfDots = 3

    for (z in 0 until nOfDots) {
        x[z] = 50 - z * 10
        y[z] = 50
    }

    locateApple()

    timer = Timer(delay, this)
    timer!!.start()
}

initGame()方法中,我们创建蛇,在板上随机放置一个苹果,然后启动计时器。

private fun doDrawing(g: Graphics) {

    if (inGame) {

        g.drawImage(apple, appleX, appleY, this)

        for (z in 0 until nOfDots) {
            if (z == 0) {
                g.drawImage(head, x[z], y[z], this)
            } else {
                g.drawImage(ball, x[z], y[z], this)
            }
        }

        Toolkit.getDefaultToolkit().sync()

    } else {

        gameOver(g)
    }
}

doDrawing()方法中,我们绘制了苹果和蛇对象。 如果游戏结束,我们将根据消息绘制游戏。

private fun gameOver(g: Graphics) {

    val msg = "Game Over"
    val small = Font("Helvetica", Font.BOLD, 14)
    val fontMetrics = getFontMetrics(small)

    val rh = RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON)

    rh[RenderingHints.KEY_RENDERING] = RenderingHints.VALUE_RENDER_QUALITY

    (g as Graphics2D).setRenderingHints(rh)

    g.color = Color.white
    g.font = small
    g.drawString(msg, (boardWidth - fontMetrics.stringWidth(msg)) / 2, 
        boardHeight / 2)
}

gameOver()方法在窗口中间绘制"Game Over"消息。 我们使用渲染提示来平滑地绘制消息。 我们使用字体指标来获取消息的大小。

private fun checkApple() {

    if (x[0] == appleX && y[0] == appleY) {

        nOfDots++
        locateApple()
    }
}

如果苹果与头部碰撞,我们会增加蛇的关节数。 我们称locateApple()方法为随机放置一个新的Apple对象。

move()方法中,我们有游戏的关键算法。 要了解它,请看一下蛇是如何运动的。 我们控制蛇的头。 我们可以使用光标键更改其方向。 其余关节在链上向上移动一个位置。 第二关节移动到第一个关节的位置,第三关节移动到第二个关节的位置,依此类推。

for (z in nOfDots downTo 1) {
    x[z] = x[z - 1]
    y[z] = y[z - 1]
}

该代码将关节向上移动。

if (leftDirection) {
    x[0] -= dotSize
}

这条线将头向左移动。

checkCollision()方法中,我们确定蛇是否击中了自己或撞墙之一。

for (z in nOfDots downTo 1) {

    if (z > 4 && x[0] == x[z] && y[0] == y[z]) {
        inGame = false
    }
}

如果蛇用头撞到其关节之一,则游戏结束。

if (y[0] >= boardHeight) {
    inGame = false
}

如果蛇击中了棋盘的底部,则游戏结束。

Snake.kt

package com.zetcode

import java.awt.EventQueue
import javax.swing.JFrame

class Snake : JFrame() {

    init {

        initUI()
    }

    private fun initUI() {

        add(Board())

        title = "Snake"

        isResizable = false
        pack()

        setLocationRelativeTo(null)
        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
    }

    companion object {

        @JvmStatic
        fun main(args: Array<String>) {

            EventQueue.invokeLater {
                val ex = Snake()
                ex.isVisible = true
            }
        }
    }
}

这是主要的类。

isResizable = false
pack()

isResizable属性会影响某些平台上JFrame容器的插入。 因此,在pack()方法之前调用它很重要。 否则,蛇的头部与右边界和底边界的碰撞可能无法正常进行。

Snake

图:贪食蛇

这是 Kotlin 和 Swing 中的贪食蛇游戏。 您可能也对相关教程感兴趣: Kotlin Swing 教程Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin Swing 教程

原文: http://zetcode.com/kotlin/swing/

Kotlin Swing 教程展示了如何在 Kotlin 中创建 Swing GUI 应用。 代码示例和图像可从作者的 Github Kotlin-Swing 存储库中获得。

Swing 是 Java 编程语言的主要 GUI 工具包。 它是 JFC(Java 基础类)的一部分,JFC 是用于为 Java 程序提供图形用户界面的 API。

Kotlin Swing JFrame

在第一个示例中,我们在屏幕上显示一个基本窗口。 使用JFrame创建主应用窗口。

KotlinSwingSimpleEx.kt

package com.zetcode

import java.awt.EventQueue
import javax.swing.*

class KotlinSwingSimpleEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setSize(300, 200)
        setLocationRelativeTo(null)
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingSimpleEx("Simple")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    EventQueue.invokeLater(::createAndShowGUI)
}

窗口位于屏幕中央。

class KotlinSwingSimpleEx(title: String) : JFrame() {

KotlinSwingSimpleEx继承自JFrame组件。 JFrame是顶级容器。 容器的目的是保存应用的组件。

setTitle(title)

应用的标题由setTitle()设置。

defaultCloseOperation = JFrame.EXIT_ON_CLOSE

defaultCloseOperation设置关闭框时默认发生的操作。 在我们的情况下,我们退出该应用。

setSize(300, 200)

我们用setSize()设置初始大小。

setLocationRelativeTo(null)

这条线用于使窗口在屏幕上居中。

val frame = KotlinSwingSimpleEx("Simple")
frame.isVisible = true

我们创建应用框架并将其显示在屏幕上。

EventQueue.invokeLater(::createAndShowGUI)

invokeLater()方法将应用放置在 Swing 事件队列中。 它用于确保所有 UI 更新都是并发安全的。

Simple example

图:简单 example

Kotlin Swing JButton

在下一个示例中,我们有一个关闭按钮。 使用JButton创建一个按钮组件。 当我们单击按钮时,应用终止。

KotlinSwingCloseButtonEx.kt

package com.zetcode

import java.awt.EventQueue
import javax.swing.*

class KotlinSwingCloseButtonEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        val closeBtn = JButton("Close")

        closeBtn.addActionListener { System.exit(0) }

        createLayout(closeBtn)

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setSize(300, 200)
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

        val gl = GroupLayout(contentPane)
        contentPane.layout = gl

        gl.autoCreateContainerGaps = true

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingCloseButtonEx("Close button")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    EventQueue.invokeLater(::createAndShowGUI)
}

我们将JButton放置在窗口上,然后向该按钮添加一个动作监听器。

val closeBtn = JButton("Close")

创建一个按钮组件。 构造器将字符串标签作为参数。

closeBtn.addActionListener { System.exit(0) }

使用addActionListener()将动作监听器添加到按钮。 该操作通过调用System.exit()方法来终止应用。

createLayout(closeBtn)

子组件(在我们的情况下是一个按钮)需要放入容器中。 我们将任务委托给createLayout()方法。

val gl = GroupLayout(contentPane)
contentPane.layout = gl

JFrame的内容窗格是放置子组件的区域。 子级由专门的不可见组件(称为布局管理器)组织。 BorderLayout是内容窗格的默认布局管理器。 该管理器非常简单,仅在少数情况下有用。 我们使用功能更强大,更灵活的GroupLayout管理器。

gl.autoCreateContainerGaps = true

autoCreateContainerGaps属性在组件和容器边缘之间创建间隙。 空间或间隙是每个应用设计的重要组成部分。

gl.setHorizontalGroup(gl.createSequentialGroup()
        .addComponent(arg[0])
)

gl.setVerticalGroup(gl.createSequentialGroup()
        .addComponent(arg[0])
)

GroupLayout管理器独立定义每个大小的布局。 第一步,我们沿着水平轴布置组件; 在另一步骤中,我们沿垂直轴布置组件。 在两种布局中,我们都可以顺序或并行排列组件。 在水平布局中,一行组件称为顺序组,而一列组件称为并行组。 在垂直布局中,一列组件称为顺序组,一排组件称为并行组。

在我们的示例中,我们只有一个按钮,因此布局非常简单。 对于每个维度,我们以按钮组件作为参数调用addComponent()方法。 (必须为两个维度都添加每个子组件。)

Close button

图:关闭按钮

Kotlin Swing JLabel

JLabel组件用于显示文本,颜色或图像。

KotlinSwingStandardColoursEx.kt

package com.zetcode

import java.awt.Color
import java.awt.Dimension
import java.awt.EventQueue
import javax.swing.GroupLayout
import javax.swing.JFrame
import javax.swing.JLabel
import javax.swing.SwingConstants.LEADING

class KotlinSwingStandardColoursEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        val stdCols = arrayOf<Color>(Color.black, Color.blue, Color.cyan, 
            Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, 
            Color.orange, Color.pink, Color.red, Color.white, Color.yellow)

        val labels = stdCols.map {
            JLabel("", null, LEADING).apply {

                minimumSize = Dimension(90, 40)
                background = it
                isOpaque = true
            }
        }

        createLayout(labels)

        setTitle(title)
        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setLocationRelativeTo(null)
    }

    private fun createLayout(labels: List<JLabel>) {

        val gl = GroupLayout(contentPane)
        contentPane.layout = gl

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(gl.createParallelGroup()
                .addGroup(gl.createSequentialGroup()
                        .addComponent(labels[0])
                        .addComponent(labels[1])
                        .addComponent(labels[2])
                        .addComponent(labels[3]))
                .addGroup(gl.createSequentialGroup()
                        .addComponent(labels[4])
                        .addComponent(labels[5])
                        .addComponent(labels[6])
                        .addComponent(labels[7]))
                .addGroup(gl.createSequentialGroup()
                        .addComponent(labels[8])
                        .addComponent(labels[9])
                        .addComponent(labels[10])
                        .addComponent(labels[11]))
                .addComponent(labels[12])
        )

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addGroup(gl.createParallelGroup()
                        .addComponent(labels[0])
                        .addComponent(labels[1])
                        .addComponent(labels[2])
                        .addComponent(labels[3]))
                .addGroup(gl.createParallelGroup()
                        .addComponent(labels[4])
                        .addComponent(labels[5])
                        .addComponent(labels[6])
                        .addComponent(labels[7]))
                .addGroup(gl.createParallelGroup()
                        .addComponent(labels[8])
                        .addComponent(labels[9])
                        .addComponent(labels[10])
                        .addComponent(labels[11]))
                .addComponent(labels[12])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingStandardColoursEx("Standard colours")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    EventQueue.invokeLater(::createAndShowGUI)
}

该示例显示了 13 个JLabel组件; 每个标签具有不同的背景色。 JLabel通常用于显示文本; 但它也可以显示颜色。

val stdCols = arrayOf<Color>(Color.black, Color.blue, Color.cyan, 
    Color.darkGray, Color.gray, Color.green, Color.lightGray, Color.magenta, 
    Color.orange, Color.pink, Color.red, Color.white, Color.yellow)

在这里,我们有一个内置颜色值的数组。

val labels = stdCols.map {
    JLabel("", null, LEADING).apply {

        minimumSize = Dimension(90, 40)
        background = it
        isOpaque = true
    }
}

标签以一定的大小和背景色创建。

Standard colours

图:标准颜色

JCheckBox

JCheckBox是带有标签的框,该标签具有两种状态:开和关。 如果选中此复选框,则在复选框中用勾号表示。 复选框可用于在启动时显示或隐藏启动屏幕,切换工具栏的可见性等。

通过JCheckBox可以使用ActionListenerItemListener。 通常使用后一种选项。 ItemListener是用于接收项目事件的接口。 对处理项目事件感兴趣的类,例如观察者,实现此接口。 使用组件的addItemListener()方法向组件注册观察者对象。 发生项目选择事件时,将调用观察者的itemStateChanged()方法。

KotlinSwingCheckBoxEx.kt

package com.zetcode

import java.awt.EventQueue
import java.awt.event.ItemEvent
import javax.swing.GroupLayout
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JFrame

class KotlinSwingCheckBoxEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        val checkBox = JCheckBox("Show title", true)

        checkBox.addItemListener { e ->
            val sel: Int = e.stateChange
            if (sel == ItemEvent.SELECTED) {
                setTitle("JCheckBox")
            } else {
                setTitle("")
            }
        }

        createLayout(checkBox)

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setSize(300, 200)
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

        val gl = GroupLayout(contentPane)
        contentPane.layout = gl

        gl.autoCreateContainerGaps = true

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        gl.setVerticalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingCheckBoxEx("JCheckBox")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    EventQueue.invokeLater(::createAndShowGUI)
}

我们的代码示例根据是否选中复选框来显示或隐藏窗口的标题。

val checkBox = JCheckBox("Show title", true)

JCheckBox已创建。 此构造器将文本和复选框的状态作为参数。 最初已选中该复选框。

checkBox.addItemListener { e ->
    val sel: Int = e.stateChange
    if (sel == ItemEvent.SELECTED) {
        setTitle("JCheckBox")
    } else {
        setTitle("")
    }
}

项目监听器随addItemListener()添加。 根据复选框的状态,我们显示或隐藏窗口标题。

JCheckBox

图:JCheckBox

Kotlin Swing 图标

在下一个示例中,我们在JLabel组件中显示图标。

KotlinSwingLabelIconEx.kt

package com.zetcode

import javax.swing.*

class KotlinSwingLabelIconEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        val lbl1 = JLabel(ImageIcon("src/main/resources/cpu.png"))
        val lbl2 = JLabel(ImageIcon("src/main/resources/drive.png"))
        val lbl3 = JLabel(ImageIcon("src/main/resources/laptop.png"))
        val lbl4 = JLabel(ImageIcon("src/main/resources/player.png"))

        createLayout(lbl1, lbl2, lbl3, lbl4)

        setTitle(title)
        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setLocationRelativeTo(null)
    }

    private fun createLayout(vararg arg: JComponent) {

        val gl = GroupLayout(contentPane)
        contentPane.layout = gl

        gl.autoCreateContainerGaps = true
        gl.autoCreateGaps = true

        gl.setHorizontalGroup(gl.createSequentialGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
                .addComponent(arg[2])
                .addComponent(arg[3])
        )

        gl.setVerticalGroup(gl.createParallelGroup()
                .addComponent(arg[0])
                .addComponent(arg[1])
                .addComponent(arg[2])
                .addComponent(arg[3])
        )

        pack()
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingLabelIconEx("Icons")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    SwingUtilities.invokeLater(::createAndShowGUI)
}

该示例在一行中显示了四个图像。

val lbl1 = JLabel(ImageIcon("src/main/resources/cpu.png"))

图像路径被传递到ImageIcon

ImageIcon

图:图像Icon

Kotlin Swing 菜单示例

JMenuBar实现菜单栏。 JMenu实现菜单,该菜单是包含JMenuItems的弹出窗口,当用户在JMenuBar上选择一个项目时显示。 JMenuItem实现菜单中的项目。 用户选择它来执行操作。

KotlinSwingSimpleMenuExEx.kt

package com.zetcode

import java.awt.EventQueue
import java.awt.event.ActionEvent
import java.awt.event.KeyEvent
import javax.swing.*

class KotlinSwingSimpleMenuExEx(title: String) : JFrame() {

    init {
        createUI(title)
    }

    private fun createUI(title: String) {

        setTitle(title)

        createMenuBar()

        defaultCloseOperation = JFrame.EXIT_ON_CLOSE
        setSize(300, 200)
        setLocationRelativeTo(null)
    }

    private fun createMenuBar() {

        val menubar = JMenuBar()
        val icon = ImageIcon("src/main/resources/exit.png")

        val file = JMenu("File")
        file.mnemonic = KeyEvent.VK_F

        val eMenuItem = JMenuItem("Exit", icon)
        eMenuItem.mnemonic = KeyEvent.VK_E
        eMenuItem.toolTipText = "Exit application"
        eMenuItem.addActionListener { _: ActionEvent -> System.exit(0) }

        file.add(eMenuItem)
        menubar.add(file)

        jMenuBar = menubar
    }
}

private fun createAndShowGUI() {

    val frame = KotlinSwingSimpleMenuExEx("Simple menu")
    frame.isVisible = true
}

fun main(args: Array<String>) {
    EventQueue.invokeLater(::createAndShowGUI)
}

该示例创建一个带有一个菜单项的简单菜单。 选择退出菜单项,我们关闭应用。

val menubar = JMenuBar()

使用JMenuBar创建菜单栏。

val icon = ImageIcon("src/main/resources/exit.png")

菜单中显示退出图标。

val file = JMenu("File")
file.mnemonic = KeyEvent.VK_F

使用JMenu类创建菜单对象。 也可以通过键盘访问菜单。 要将菜单绑定到特定键,我们使用setMnemonic()方法。 在我们的情况下,可以使用Alt + F + E 打开菜单。

eMenuItem.toolTipText = "Exit application"

此代码行为菜单项创建工具提示。

eMenuItem.addActionListener { _: ActionEvent -> System.exit(0) }

JMenuItem是一种特殊的按钮组件。 我们向它添加一个动作监听器; 选择后将终止应用。

file.add(eMenuItem)
menubar.add(file)

菜单项被添加到菜单对象,菜单对象被插入菜单栏。

jMenuBar = menubar

菜单栏设置为JFramejMenubar属性。

Simple menu

图:简单菜单

在本教程中,我们介绍了使用 Kotlin 语言的 Swings 工具包。 您可能也对相关教程感兴趣: Kotlin Hello World 教程Kotlin 控制流Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin 字符串

原文: http://zetcode.com/kotlin/strings/

Kotlin 字符串教程展示了如何在 Kotlin 中使用字符串。

字符串是编程语言中的基本数据类型。 在 Kotlin 中,String类表示字符串。 Kotlin 字符串字面值被实现为此类的实例。 Kotlin 使用双引号创建字符串字面值。

Kotlin 具有用于处理字符串的丰富 API。 它包含许多用于各种字符串操作的方法。 Kotlin/Java 字符串是不可变的,这意味着所有修改操作都会创建新的字符串,而不是就地修改字符串。

Kotlin 字符串示例

在第一个示例中,我们有一个简单的 Kotlin 字符串示例。

KotlinStringBasic.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = "Today is a sunny day."
    println(s)

    println("Old " + "bear")

    println("The string has " + s.length + " characters")
}

该示例创建一个字符串,使用字符串连接操作,并确定该字符串的宽度。

val s = "Today is a sunny day."
println(s)

将创建一个字符串字面值并将其传递给s变量。 使用println()将字符串打印到控制台。

println("Old " + "bear")

在 Kotlin 中,字符串与+运算符连接在一起。

println("The string has " + s.length + " characters")

字符串的长度由length属性确定。

Today is a sunny day.
Old bear
The string has 21 characters

这是输出。

Kotlin 字符串索引

字符串是字符序列。 我们可以通过索引操作从字符串中获取特定字符。

KotlinStringIndexes.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = "blue sky"

    println(s[0])
    println(s[s.length-1])

    println(s.first())
    println(s.last())
}

该示例显示了如何获取字符串的第一个和最后一个字符。 它使用索引操作和替代的字符串方法。

println(s[0])
println(s[s.length-1])

索引从零开始; 因此,第一个字符的索引为零。 字符的索引放在方括号之间。

println(s.first())
println(s.last())

first()方法返回字符串的第一个字符,last()返回字符串的最后一个字符。

Kotlin 字符串插值

字符串插值是变量替换,其值在字符串中。 在 Kotlin 中,我们使用$字符插入变量,并使用${}插入表达式。

Kotlin 字符串格式化比基本插值功能更强大。

KotlinStringInterpolate.kt

package com.zetcode

fun main(args: Array<String>) {

    val name = "Peter"
    val age = 34

    println("$name is $age years old")

    val msg = "Today is a sunny day"

    println("The string has ${msg.length} characters")
}

该示例显示了如何在 Kotlin 中进行字符串插值。

val name = "Peter"
val age = 34

我们有两个变量。

println("$name is $age years old")

这两个变量在字符串内插; 即用它们的值替换它们。

println("The string has ${msg.length} characters")

在这里,我们得到字符串的长度。 由于它是一个表达式,因此需要将其放在{}括号内。

Peter is 34 years old
The string has 20 characters

这是输出。

Kotlin 字符串比较

我们可以使用==运算符和compareTo()方法来比较字符串内容。

KotlinCompareStrings.kt

package com.zetcode

fun main(args: Array<String>) {

    val s1 = "Eagle"
    val s2 = "eagle"

    if (s1 == s2) {

        println("Strings are equal")
    }  else {

        println("Strings are not equal")
    }

    println("Ignoring case")

    val res = s1.compareTo(s2, true)

    if (res == 0) {

        println("Strings are equal")
    }  else {

        println("Strings are not equal")
    }
}

在示例中,我们比较两个字符串。

if (s1 == s2) {

==运算符比较结构相等性,即两个字符串的内容。

val res = s1.compareTo(s2, true)

compareTo()方法按字典顺序比较两个字符串,可以忽略大小写。

Kotlin 字符串转义字符

字符串转义字符是执行特定操作的特殊字符。 例如,\n字符开始换行。

KotlinStringEscapeCharacters.kt

package com.zetcode

fun main(args: Array<String>) {

    println("Three\t bottles of wine")
    println("He said: \"I love ice skating\"")
    println("Line 1:\nLine 2:\nLine 3:")
}

该示例显示了 Kotlin 中的转义字符。

println("He said: \"I love ice skating\"")

我们通过转义双引号的原始功能,将双引号插入字符串字面值中。

println("Line 1:\nLine 2:\nLine 3:")

使用\n,我们创建了三行。

Three    bottles of wine
He said: "I love ice skating"
Line 1:
Line 2:
Line 3:

这是输出。

Kotlin 字符串大小写

Kotlin 具有处理字符串字符大小写的方法。

KotlinStringCase.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = "young eagle"

    println(s.capitalize())
    println(s.toUpperCase())
    println(s.toLowerCase())

    println("Hornet".decapitalize())
}

该示例提出了四种方法:capitalize()toUpperCase()toLowerCase()decapitalize()

Young eagle
YOUNG EAGLE
young eagle
hornet

这是示例的输出。

Kotlin 空/空白字符串

Kotlin 区分空字符串和空字符串。 空字符串不包含任何字符,空白字符串包含任意数量的空格。

KotlinStringEmptyBlank.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = "\t"

    if (s.isEmpty()) {

        println("The string is empty")
    } else {

        println("The string is not empty")
    }

    if (s.isBlank()) {

        println("The string is blank")
    } else {

        println("The string is not blank")
    }
}

该示例测试字符串是否平淡且为空。

if (s.isEmpty()) {

如果字符串为空,则isEmpty()返回true

if (s.isBlank()) {

如果字符串为空白,则isBlank()返回true

The string is not empty
The string is blank

这是示例的输出。

Kotlin 字符串空格去除

我们经常需要从字符串中去除空格字符。

KotlinStringSort.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = " Eagle\t"

    println("s has ${s.length} characters")

    val s1 = s.trimEnd()
    println("s1 has ${s1.length} characters")

    val s2 = s.trimStart()
    println("s2 has ${s2.length} characters")

    val s3 = s.trim()
    println("s2 has ${s3.length} characters")
}

该示例介绍了从字符串中去除空格的方法。

val s1 = s.trimEnd()

trimEnd()方法删除尾随空格。

val s2 = s.trimStart()

trimStart()方法删除前导空格。

val s3 = s.trim()

trim()方法同时删除尾随空格和前导空格。

Kotlin 字符串循环

Kotlin 字符串是字符序列。 我们可以循环执行此序列。

KotlinStringLoop.kt

package com.zetcode

fun main(args: Array<String>) {

    val phrase = "young eagle"

    for (e in phrase) {

        print("$e ")
    }

    println()

    phrase.forEach { e -> print(String.format("%#x ", e.toByte())) }

    println()

    phrase.forEachIndexed { idx, e -> println("phrase[$idx]=$e ")  }
}

该示例使用for循环,forEach循环和forEachIndexed循环遍历字符串。

for (e in phrase) {

    print("$e ")
}

我们使用for循环遍历字符串并打印每个字符。

phrase.forEach { e -> print(String.format("%#x ", e.toByte())) }

我们使用forEach遍历一个循环,并打印每个字符的字节值。

phrase.forEachIndexed { idx, e -> println("phrase[$idx]=$e ")  }

使用forEachIndexed,我们将打印带有索引的字符。

y o u n g   e a g l e 
0x79 0x6f 0x75 0x6e 0x67 0x20 0x65 0x61 0x67 0x6c 0x65 
phrase[0]=y 
phrase[1]=o 
phrase[2]=u 
phrase[3]=n 
phrase[4]=g 
phrase[5]=  
phrase[6]=e 
phrase[7]=a 
phrase[8]=g 
phrase[9]=l 
phrase[10]=e 

这是输出。

Kotlin 字符串过滤

filter()方法返回一个字符串,该字符串仅包含原始字符串中与给定谓词匹配的那些字符。

KotlinStringFilter.kt

package com.zetcode

fun main(args: Array<String>) {

fun Char.isEnglishVowel(): Boolean =  this.toLowerCase() == 'a'
        || this.toLowerCase() == 'e'
        || this.toLowerCase() == 'i'
        || this.toLowerCase() == 'o'
        || this.toLowerCase() == 'u'
        || this.toLowerCase() == 'y'

fun main(args: Array<String>) {

    val s = "Today is a sunny day."

    val res = s.filter { e -> e.isEnglishVowel()}

    println("There are ${res.length} vowels")
}

该示例计算字符串中的所有元音。

fun Char.isEnglishVowel(): Boolean =  this.toLowerCase() == 'a'
        || this.toLowerCase() == 'e'
        || this.toLowerCase() == 'i'
        || this.toLowerCase() == 'o'
        || this.toLowerCase() == 'u'
        || this.toLowerCase() == 'y'

我们创建一个扩展函数; 对于英语元音,它返回true

val res = s.filter { e -> e.isEnglishVowel()}

扩展函数在filter()方法中调用。

Kotlin 字符串 startsWith/endsWith

如果字符串以指定的前缀开头,则startsWith()方法返回true;如果字符串以指定的字符结尾,则endsWith()返回true

KotlinStringStartEnd.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("tank", "boy", "tourist", "ten",
            "pen", "car", "marble", "sonnet", "pleasant",
            "ink", "atom")

    val res = words.filter { e -> startWithT(e) }
    println(res)

    val res2 = words.filter { e -> endWithK(e) }
    println(res2)
}

fun startWithT(word: String): Boolean {

    return word.startsWith("t")
}

fun endWithK(word: String): Boolean {

    return word.endsWith("k")
}

在示例中,我们有一个单词列表。 通过上述方法,我们找出哪些单词以"t""k"开头。

val words = listOf("tank", "boy", "tourist", "ten",
        "pen", "car", "marble", "sonnet", "pleasant",
        "ink", "atom")

使用listOf(),我们定义了一个单词列表。

val res = words.filter { e -> startWithT(e) }
println(res)

val res2 = words.filter { e -> endWithK(e) }
println(res2)

我们在filter()方法中调用了两个自定义函数。

fun startWithT(word: String): Boolean {

    return word.startsWith("t")
}

startWithT()是一个自定义谓词函数,如果字符串以't'开头,则返回true

[tank, tourist, ten]
[tank, ink]

这是输出。

Kotlin 字符串替换

replace()方法返回通过将所有出现的旧字符串替换为新字符串而获得的新字符串。

KotlinStringReplace.kt

package com.zetcode

fun main(args: Array<String>) {

    val s = "Today is a sunny day."

    val w = s.replace("sunny", "rainy")
    println(w)
}

该示例用多雨代替晴天。 返回一个新的修改后的字符串。 原始字符串未修改。

Kotlin toString

在字符串上下文中使用对象时,将调用toString()方法; 例如它被打印到控制台。 其目的是提供对象的字符串表示形式。

KotlinToString.kt

package com.zetcode

class City(private var name: String, private var population: Int) {

    override fun toString(): String {
        return "$name has population $population"
    }
}

fun main(args: Array<String>) {

    val cities = listOf(City("Bratislava", 432000),
            City("Budapest", 1759000),
            City("Prague", 1280000))

    cities.forEach { e -> println(e) }
}

该示例创建一个城市对象列表。 我们遍历列表并将对象打印到控制台。

override fun toString(): String {
    return "$name has population $population"
}

我们将覆盖toString()的默认实现。 它返回一个字符串,表明一个城市具有指定的人口。

Bratislava has population 432000
Budapest has population 1759000
Prague has population 1280000

这是输出。

Kotlin 原始字符串

原始字符串由三引号"""分隔。它没有转义,并且可以包含换行符和任何其他字符。

KotlinRawString.kt

package com.zetcode

fun main(args: Array<String>) {

    val sonnet = """
        Not marble, nor the gilded monuments
        Of princes, shall outlive this powerful rhyme;
        But you shall shine more bright in these contents
        Than unswept stone, besmear'd with sluttish time.
        When wasteful war shall statues overturn,
        And broils root out the work of masonry,
        Nor Mars his sword nor war's quick fire shall burn
        The living record of your memory.
        'Gainst death and all-oblivious enmity
        Shall you pace forth; your praise shall still find room
        Even in the eyes of all posterity
        That wear this world out to the ending doom.
        So, till the judgment that yourself arise,
        You live in this, and dwell in lovers' eyes.
        """

    println(sonnet.trimIndent())
}

在示例中,我们有一个多行字符串,其中包含一个经文。 当字符串被打印时,我们去除缩进。

Kotlin 字符串填充

Kotlin 具有将字符串填充到指定字符或空格的方法。

KotlinStringPad.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = intArrayOf(657, 122, 3245, 345, 99, 18)

    nums.toList().forEach { e -> println(e.toString().padStart(20, '.')) }
}

该示例使用padStart()将数字用点字符填充。

.................657
.................122
................3245
.................345
..................99
..................18

这是输出。

在本教程中,我们介绍了 Kotlin 字符串。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin Hello World 教程Kotlin 变量教程Kotlin 控制流Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin 列表

原文: http://zetcode.com/kotlin/lists/

Kotlin 列表教程显示了如何在 Kotlin 中使用列表。 列表是元素的一般有序集合。

Kotlin 区分只读列表和可变列表。 用listOf()创建只读列表,用mutableListOf()创建可变列表。

Kotlin listOf()

listOf()方法在 Kotlin 中创建一个新的只读列表。

KotlinListOf.kt

package com.zetcode

fun main() {

    val words = listOf("pen", "cup", "dog", "spectacles")
    println("The list contains ${words.size} elements.")
}

该示例使用listOf()创建新的单词列表。 列表的大小由size属性确定。

Kotlin List基础

在下一个示例中,我们有一个简单的 Kotlin List示例。

KotlinListBasic.kt

package com.zetcode

fun main() {

    val nums = listOf(11, 5, 3, 8, 1, 9, 6, 2)

    val len = nums.count()
    val max = nums.max()
    val min = nums.min()
    val sum = nums.sum()
    val avg = nums.average()

    val msg = """
               max: $max, min: $min,
               count: $len, sum: $sum,
               average: $avg
              """
    println(msg.trimIndent())

}

该示例创建一个数字列表并计算一些统计信息。

val nums = listOf(11, 5, 3, 8, 1, 9, 6, 2)

使用listOf()函数创建 Kotlin 只读列表。

val len = nums.count()
val max = nums.max()
val min = nums.min()
val sum = nums.sum()
val avg = nums.average()

我们计算值的数量,最大值,最小值,总和和平均值。

max: 11, min: 1,
count: 8, sum: 45,
average: 5.625

这是输出。

Kotlin 列表索引

列表的每个元素都有一个索引。 Kotlin 列表索引从零开始。 最后一个元素的索引为len-1

KotlinListIndex.kt

package com.zetcode

fun main() {

    val words = listOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles", "cup", "bread")

    val w1 = words.get(0)
    println(w1)

    val w2 = words[0]
    println(w2)

    val i1 = words.indexOf("cup")
    println("The first index of cup is $i1")

    val i2 = words.lastIndexOf("cup")
    println("The last index of cup is $i2")

    val i3 = words.lastIndex
    println("The last index of the list is $i3")
}

该示例介绍了 Kotlin List索引操作。

val w1 = words.get(0)

使用get()方法检索元素。 该方法将要检索的元素的索引作为参数。

val w2 = words[0]

我们还可以使用经典的 C 索引操作。

val i1 = words.indexOf("cup")

indexOf()返回列表中单词首次出现的索引。

val i2 = words.lastIndexOf("cup")

lastIndexOf()返回列表中单词最后一次出现的索引。

val i3 = words.lastIndex

lastIndex属性返回列表中最后一项的索引;如果列表为空,则返回-1

pen
pen
The first index of cup is 1
The last index of cup is 7
The last index of the list is 8

这是输出。

Kotlin 列表计数

count()方法返回列表中的元素数。

KotlinListCount.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val len = nums.count()
    println("There are $len elements")

    val size = nums.size
    println("The size of the list is $size")    

    val n1 = nums.count { e -> e < 0 }
    println("There are $n1 negative values")

    val n2 = nums.count { e -> e % 2 == 0 }
    println("There are $n2 even values")
}

该示例返回列表中值的数量,负值的数量和偶数的数量。

val len = nums.count()
println("There are $len elements")

val size = nums.size
println("The size of the list is $size") 

我们可以使用count()方法或size属性来确定列表中的元素数量。

val n1 = nums.count { e -> e < 0 }

count()可以将谓词函数作为参数。 在我们的情况下,它对于小于 0 的值返回true

val n2 = nums.count { e -> e % 2 == 0 }

我们获得列表中的偶数个数。

There are 11 elements
The size of the list is 11
There are 3 negative values
There are 5 even values

这是输出。

Kotlin 列表第一个和最后一个元素

我们有方法来获取列表的第一个和最后一个元素。

KotlinListFirstLast.kt

package com.zetcode

fun main() {

    val words = listOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles")

    val w1 = words.first()
    println(w1)

    val w2 = words.last()
    println(w2)

    val w3 = words.findLast { w -> w.startsWith('c') }
    println(w3)

    val w4 = words.first { w -> w.startsWith('c') }
    println(w4)
}

该示例创建一个单词列表。 我们得到列表的第一个和最后一个元素。

val w1 = words.first()

我们用first()获得第一个元素。

val w2 = words.last()

我们用last()获得最后一个元素。

val w3 = words.findLast { w -> w.startsWith('c') }

我们以findLast()检索以'c'开头的列表的最后一个元素。

val w4 = words.first { w -> w.startsWith('c') }

我们以first()检索以'c'开头的列表的第一个元素。

pen
spectacles
coal
cup

这是输出。

Kotlin 列表迭代

列表迭代或列表循环是一个遍历列表元素的过程。

KotlinListIterate.kt

package com.zetcode

fun main() {

    val words = listOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles")

    words.forEach { e -> print("$e ") }
    println()

    for (word in words) {

        print("$word ")
    }

    println()

    for (i in 0 until words.size) {

        print("${words[i]} ")
    }

    println()

    words.forEachIndexed({i, e -> println("words[$i] = $e")})

    val it: ListIterator<String> = words.listIterator()

    while (it.hasNext()) {

        val e = it.next()
        print("$e ")
    }

    println()
}

该示例显示了 Kotlin 中遍历列表的五种方法。

words.forEach { e -> print("$e ") }

forEach()对每个列表元素执行给定的操作。 我们为它传递了一个匿名函数,该函数将打印当前元素。

for (word in words) {

    print("$word ")
}

我们用for循环列表。 for循环逐个遍历列表。 在每个循环中,word变量指向列表中的下一个元素。

for (i in 0 until words.size) {

    print("${words[i]} ")
}

另一种for循环利用列表的大小。 until关键字创建一系列列表索引。

words.forEachIndexed({i, e -> println("words[$i] = $e")})

使用forEachIndexed()方法,我们遍历具有每次迭代可用索引和值的列表。

val it: ListIterator<String> = words.listIterator()

while (it.hasNext()) {

    val e = it.next()
    print("$e ")
}

最后一种方法是使用ListIteratorwhile循环。

pen cup dog person cement coal spectacles 
pen cup dog person cement coal spectacles 
pen cup dog person cement coal spectacles 
words[0] = pen
words[1] = cup
words[2] = dog
words[3] = person
words[4] = cement
words[5] = coal
words[6] = spectacles
pen cup dog person cement coal spectacles 

这是输出。

Kotlin 列表排序

以下示例显示如何在 Kotlin 中对列表值进行排序。 由于使用listOf()创建的列表是只读的,因此这些方法不会更改列表,但会返回新的修改后的列表。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinListSorting.kt

package com.zetcode

import com.zetcode.bean.Car

fun main() {

    val nums = listOf(11, 5, 3, 8, 1, 9, 6, 2)

    val sortAsc = nums.sorted()
    println(sortAsc)

    val sortDesc = nums.sortedDescending()
    println(sortDesc)

    val revNums = nums.reversed()
    println(revNums)

    val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val res = cars.sortedBy { car -> car.name }
    res.forEach { e -> println(e) }

    println("*************")

    val res2 = cars.sortedByDescending { car -> car.name }
    res2.forEach { e -> println(e) }
}

该示例按升序和降序对列表值进行排序,反转列表元素,并按名称对汽车对象进行排序。

val sortAsc = nums.sorted()

sorted()方法返回根据自然排序顺序排序的所有元素的列表。

val sortDesc = nums.sortedDescending()

sortedDescending()方法返回所有元素按照其自然排序顺序降序排列的列表。

val revNums = nums.reversed()

reversed()方法返回具有相反顺序元素的列表。

val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

我们创建汽车对象列表。 这些对象可以按名称或价格排序。

val res = cars.sortedBy { car -> car.name }

使用sortedBy(),我们按名称对汽车进行升序排序。

val res2 = cars.sortedByDescending { car -> car.name }

使用sortedByDescending(),我们按名称对汽车进行降序排序。

[1, 2, 3, 5, 6, 8, 9, 11]
[11, 9, 8, 6, 5, 3, 2, 1]
[2, 6, 9, 1, 8, 3, 5, 11]
Car(name=Mazda, price=6300)
Car(name=Mercedes, price=18600)
Car(name=Skoda, price=5670)
Car(name=Toyota, price=12400)
*************
Car(name=Toyota, price=12400)
Car(name=Skoda, price=5670)
Car(name=Mercedes, price=18600)
Car(name=Mazda, price=6300)

这是输出。

Kotlin 列表包含

使用contains()方法,我们可以检查列表是否包含指定的元素。

KotlinListContains.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val r = nums.contains(4)

    if (r) println("The list contains 4")
    else println("The list does not contain 4")

    val r2 = nums.containsAll(listOf(1, -1))

    if (r2) println("The list contains -1 and 1")
    else println("The list does not contain -1 and 1")
}

可以检查列表是否包含一个或多个元素。

val r = nums.contains(4)

在这里,我们检查nums列表是否包含 4。该方法返回布尔值。

val r2 = nums.containsAll(listOf(1, -1))

此行检查列表是否包含两个值:1 和 -1。

The list contains 4
The list contains -1 and 1

这是输出。

Kotlin 可变列表

使用mutableListOf(),我们可以在 Kotlin 中创建可变列表。 我们可以在可变列表中添加新元素,删除元素和修改元素。

KotlinListMutable.kt

package com.zetcode

fun main() {

    val nums = mutableListOf(3, 4, 5)

    nums.add(6)
    nums.add(7)
    nums.addAll(listOf(8, 9, 10))
    nums.add(0, 0)
    nums.add(1, 1)
    nums.add(2, 2)

    println(nums)

    nums.shuffle()

    println(nums)

    nums.sort()

    println(nums)

    nums.removeAt(0)
    nums.remove(10)

    println(nums)

    nums.replaceAll { e -> e * 2 }

    println(nums)

    nums.retainAll(listOf(12, 14, 16, 18))

    println(nums)    

    nums.fill(0)

    println(nums)

    nums.set(0, 22)
    println(nums[0])

    nums.clear()

    if (nums.isEmpty()) println("The list is empty")
    else println("The list is not epty")
}

该示例创建一个可变列表并提供其几种方法。

val nums = mutableListOf(3, 4, 5)

我们创建一个包含三个整数元素的可变列表。

nums.add(6)
nums.add(7)
nums.addAll(listOf(8, 9, 10))

add()在列表末尾添加一个新元素。 addAll()在列表的末尾添加了多个元素。

nums.shuffle()

shuffle()方法随机重新排列列表元素。 改组发生在原地; 即原始列表已修改。

nums.sort()

元素按其自然升序排序。

nums.removeAt(0)
nums.remove(10)

removeAt()方法删除指定索引处的元素。 remove()方法从列表中删除第一次出现的指定元素。

nums.replaceAll { e -> e * 2 }

replaceAll()方法使用给定函数修改列表的所有元素。 在我们的例子中,我们创建一个匿名函数,将每个元素乘以 2。

nums.retainAll(listOf(12, 14, 16, 18))

retainAll()方法仅保留参数中指定的元素; 其他被删除。

nums.fill(0)

fill()方法将所有元素替换为给定值。

nums.set(0, 22)

set()方法用给定元素替换列表中指定位置的元素。

nums.clear()

clear()方法从列表中删除所有元素。

if (nums.isEmpty()) println("The list is empty")
else println("The list is not epty")

使用isEmpty()方法,我们检查列表是否为空。

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[2, 3, 6, 1, 8, 0, 7, 5, 10, 9, 4]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 4, 6, 8, 10, 12, 14, 16, 18]
[12, 14, 16, 18]
[0, 0, 0, 0]
22
The list is empty

这是输出。

Kotlin 列表切片

切片是列表的一部分。 可以使用slice()方法创建切片。 该方法获取要拾取的元素的索引。

KotlinListSlice.kt

package com.zetcode

fun main() {

    val nums = listOf(1, 2, 3, 4, 5, 6)

    val nums2 = nums.slice(1..3)
    println(nums2)

    val nums3 = nums.slice(listOf(3, 4, 5))
    println(nums3)
}

在示例中,我们创建一个整数列表。 从列表中,我们产生两个切片。

val nums2 = nums.slice(1..3)

我们使用范围运算符创建包含索引为 1、2 和 3 的元素的列表切片。所有索引都包括在内。

val nums3 = nums.slice(listOf(3, 4, 5))

在第二个示例中,我们显式提供索引列表。

[2, 3, 4]
[4, 5, 6]

这是输出。

Kotlin 列表上限

下面的示例处理查找列表的最大值。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinListMax.kt

package com.zetcode

import com.zetcode.bean.Car

fun main() {

    val nums = listOf(11, 5, 23, 8, 1, 9, 6, 2)

    println(nums.max())

    val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val car = cars.maxBy { car -> car.price }
    println("The max price is ${car?.price} of ${car?.name}")
}

该示例查找整数列表和汽车对象列表的最大值。

val nums = listOf(11, 5, 23, 8, 1, 9, 6, 2)

println(nums.max())

可以使用max()轻松找到整数列表的最大值。

val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

val car = cars.maxBy { car -> car.price }
println("The max price is ${car?.price} of ${car?.name}")

处理对象时,需要指定用于查找最大值的属性。 maxBy()方法具有选择器函数,用于选择汽车的price属性。

23
The max price is 18600 of Mercedes

这是输出。

Kotlin 列表过滤器

过滤是一种操作,只有满足某些条件的元素才能通过。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinListFilter.kt

package com.zetcode

import com.zetcode.bean.Car

fun main(args: Array<String>) {

    val words = listOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles")

    val words2 = words.filter { e -> e.length == 3 }
    words2.forEach { e -> print("$e ") }

    println()

    val words3 = words.filterNot { e -> e.length == 3 }

    words3.forEach { e -> print("$e ") }

    println()

    val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val res = cars.filter { car -> car.price > 10000 }
    res.forEach { e -> println(e) }
}

该示例展示了对 Kotlin 列表的过滤操作。

val words2 = words.filter { e -> e.length == 3 }

filter()方法采用谓词函数作为参数。 谓词给出了元素必须满足的条件。 我们过滤掉长度等于 3 的单词。

val words3 = words.filterNot { e -> e.length == 3 }

filterNot()的作用相反:它允许通过不符合给定条件的元素。

val cars = listOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

val res = cars.filter { car -> car.price > 10000 }

这些行过滤掉价格大于 10000 的汽车对象。

pen cup dog 
person cement coal spectacles 
Car(name=Toyota, price=12400)
Car(name=Mercedes, price=18600)

这是输出。

Kotlin 列表映射

映射操作通过在列表的每个元素上应用转换函数来返回修改后的列表。

KotlinListMap.kt

package com.zetcode

fun main() {

    val nums = listOf(1, 2, 3, 4, 5, 6)

    val nums2 = nums.map { e -> e * 2 }
    println(nums2)
}

我们有一个整数列表。 使用map()方法,我们将每个列表元素乘以 2。

[2, 4, 6, 8, 10, 12]

这是示例输出。

Kotlin 列表归约

归约是将列表值聚合为单个值的终端操作。 reduce()方法对一个累加器和每个元素(从左到右)应用一个函数,以将其减小为单个值。

KotlinListReduce.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, 1, 7, 6, 8, 9)

    val sum = nums.reduce { total, next -> total + next }
    println(sum)

    val colours = listOf("red", "green", "white", "blue", "black")

    val res = colours.reduceRight { next, total -> "$total-$next" }
    println(res)
}

在示例中,我们对整数和字符串列表使用reduce操作。

val sum = nums.reduce { total, next -> total + next }

我们计算值的总和。 total是累加器,next是列表中的下一个值。

val res = colours.reduceRight { next, total -> "$total-$next" }

reduceRight()从最后一个元素开始累加值,并从右到左对每个元素和当前累加器值进行运算。

45
black-blue-white-green-red

这是输出。

列表折叠

折叠操作类似于缩小操作。 折叠是将列表值聚合为单个值的终端操作。 区别在于折叠从初始值开始。

KotlinListFold.kt

package com.zetcode

fun main() {

    val expenses = listOf(20, 40, 80, 15, 25)

    val cash = 550

    val res = expenses.fold(cash) {total, next -> total - next}
    println(res)
}

我们有一份支出列表。 这些费用适用于初始可用现金金额。

val res = expenses.fold(cash) {total, next -> total - next}

利用fold(),我们从cash推算出所有费用,并返回剩余值。

370

这是我们减去可用金额的所有费用后的余额。

Kotlin 列表分块

有时,在进行归约时,我们需要使用列表中的更多元素。 我们可以使用chunked()方法将列表分成列表列表。

KotlinListChunked.kt

package com.zetcode

fun main() {

    val nums = listOf(1, 2, 3, 4, 5, 6)

    val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }

    println(res)
}

在示例中,我们有六个值的列表。 我们要实现以下操作:1*2 + 3*4 + 5*6。 为此,我们需要将列表分成两个值的块。

val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }

我们将列表分为两个元素的列表,然后对其进行折叠。 next是我们可以在其中使用索引操作的列表。

44

这是示例的输出。

Kotlin 列表分区

分区操作将原始集合拆分为成对的列表。 第一个列表包含其指定谓词产生true的元素,而第二个列表包含其谓词产生false的元素。

KotlinListPartition.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = listOf(4, -5, 3, 2, -1, 7, -6, 8, 9)

    val (nums2, nums3) = nums.partition { e -> e < 0 }
    println(nums2)
    println(nums3)
}

我们有一个整数列表。 使用partition()方法,我们将列表分为两个子列表; 一个包含负值,另一个包含正值。

val (nums2, nums3) = nums.partition { e -> e < 0 }

使用解构声明,我们一次性将列表分为两部分。

[-5, -1, -6]
[4, 3, 2, 7, 8, 9]

这是输出。

Kotlin 列表分组

groupBy()方法通过将给定选择器函数返回的键应用于原始列表的元素进行分组,这些键应用于每个元素。 它返回一个映射,其中每个组键都与对应元素的列表相关联。

KotlinListGroupBy.kt

package com.zetcode

fun main() {

    val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8)

    val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" }
    println(res)

    val words = listOf("as", "pen", "cup", "doll", "my", "dog", "spectacles")

    val res2 = words.groupBy { it.length }
    println(res2)
}

该示例显示了如何使用groupBy()方法。

val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8)

val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" }
println(res)

这些行创建了一个映射,该映射具有两个键:"even""odd""even"指向偶数值列表,"odd"指向奇数值列表。

val words = listOf("as", "pen", "cup", "doll", "my", "dog", "spectacles")

val res2 = words.groupBy { it.length }

在这里,我们创建一个带有整数键的映射。 每个关键字将具有一定长度的单词分组。

{odd=[1, 3, 5, 7], even=[2, 4, 6, 8]}
{2=[as, my], 3=[pen, cup, dog], 4=[doll], 10=[spectacles]}

这是输出。

Kotlin 列表any()

如果至少一个元素与给定的谓词函数匹配,则any()方法返回true

KotlinListAny.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, -1, 7, 6, 8, 9)

    val r = nums.any { e -> e > 10 }
    if (r) println("There is a value greater than ten")
    else println("There is no value greater than ten")

    val r2 = nums.any { e -> e < 0 }
    if (r2) println("There is a negative value")
    else println("There is no negative value")
}

该示例显示any()的用法。

val r2 = nums.any { e -> e < 0 }

在这里,我们检查列表中是否至少包含一个负值。 该方法返回一个布尔值。

Kotlin 列表all()

如果所有元素都满足给定的谓词函数,则all()返回true

KotlinListAll.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, -1, 7, 6, 8, 9)
    val nums2 = listOf(-3, -4, -2, -5, -7, -8)

    // testing for positive only values
    val r = nums.all { e -> e > 0 }

    if (r) println("nums list contains only positive values")
    else println("nums list does not contain only positive values")

    // testing for negative only values
    val r2 = nums2.all { e -> e < 0 }

    if (r2) println("nums2 list contains only negative values")
    else println("nums2 list does not contain only negative values")
}

该示例显示all()的用法。

// testing for positive only values
val r = nums.all { e -> e > 0 }

在这里,我们测试nums列表是否仅包含正值。

Kotlin 列表删除

通过放置操作,我们从列表中排除了一些元素。

KotlinListDrop.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val nums2 = nums.drop(3)
    println(nums2)

    val nums3 = nums.dropLast(3)
    println(nums3)

    val nums4 = nums.sorted().dropWhile { e -> e < 0 }
    println(nums4)

    val nums5 = nums.sorted().dropLastWhile { e -> e > 0 }
    println(nums5)
}

该示例显示了不同放置操作的用法。

val nums2 = nums.drop(3)

使用drop()方法,我们排除了前三个元素。

val nums3 = nums.dropLast(3)

使用dropLast()方法,我们排除了最后三个元素。

val nums4 = nums.sorted().dropWhile { e -> e < 0 }

使用dropWhile()方法,我们排除了满足给定谓词函数的前 n 个元素。

val nums5 = nums.sorted().dropLastWhile { e -> e > 0 }

使用dropLastWhile()方法,我们排除了满足给定谓词函数的最后 n 个元素。

[2, 1, -1, 7, 6, -8, 9, -12]
[4, 5, 3, 2, 1, -1, 7, 6]
[1, 2, 3, 4, 5, 6, 7, 9]
[-12, -8, -1]

这是输出。

Kotlin 列表提取

提取操作是放置操作的补充。 通过选择一些元素,take方法形成一个新列表。

KotlinListTake.kt

package com.zetcode

fun main() {

    val nums = listOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val nums2 = nums.take(3)
    println(nums2)

    val nums3 = nums.takeLast(3)
    println(nums3)

    val nums4 = nums.sorted().take(3)
    println(nums4)

    val nums5 = nums.takeWhile { e -> e > 0 }
    println(nums5)

    val nums6 = nums.sortedDescending().takeWhile { e -> e > 0 }
    println(nums6)

    val nums7 = nums.takeIf { e -> e.contains(6) }
    println(nums7)
}

该示例显示了各种take方法的用法。

val nums2 = nums.take(3)

take()方法创建一个具有原始列表的前三个元素的新列表。

val nums3 = nums.takeLast(3)

takeLast()方法将最后一个元素放入新列表中。

val nums5 = nums.takeWhile { e -> e > 0 }

takeWhile()采用满足谓词函数的前 n 个元素。

val nums7 = nums.takeIf { e -> e.contains(6) }

如果满足谓词函数中的条件,则takeIf()方法将使用列表中的所有元素。

[4, 5, 3]
[-8, 9, -12]
[-12, -8, -1]
[4, 5, 3, 2, 1]
[9, 7, 6, 5, 4, 3, 2, 1]
[4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12]

这是输出。

在本教程中,我们涵盖了 Kotlin 列表。 您可能也对相关教程感兴趣: Kotlin 设置教程Kotlin 数组教程Kotlin 映射教程或列出所有 Kotlin 教程

Kotlin 映射

原文: http://zetcode.com/kotlin/maps/

Kotlin 映射教程显示了如何在 Kotlin 中使用映射。 映射是对象对的集合。

Kotlin 区分只读映射和可变映射。 使用mapOf()创建只读映射,并使用mutableMapOf()创建可变映射。

Kotlin 映射

映射是保存成对对象的集合。 每对都包含一个键和一个值。 映射键是唯一的; 该映射的每个键仅包含一个值。

Kotlin mapOf()

mapOf()方法创建具有指定内容的只读映射,并以成对的列表的形式给出,其中第一个值为键,第二个为值。

KotlinMapOf.kt

package com.zetcode

fun main() {

    val chars = mapOf(97 to "a", 98 to "b", 120 to "x")
    println(chars)

    val user = mapOf("name" to "Luke", "age" to "23")
    println(user)
}

该示例创建了两个映射。

{97=a, 98=b, 120=x}
{name=Luke, age=23}

这是输出。

Kotlin 哈希映射

可以从 Java 的HashMap创建映射。

KotlinHashMap.kt

package com.zetcode

fun main() {

    val items = HashMap<String, Int>()

    items["A"] = 90
    items["B"] = 80
    items["C"] = 70

    for ((k, v) in items) {
        println("$k = $v")
    }
}

该示例使用 Java 的HashMap创建映射,并将值和对打印到控制台。

Kotlin 映射大小

映射的大小(对数)可以使用size属性和count()方法确定。

KotlinMapSize.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)

    println("Map has ${items.size} items")
    println("Map has ${items.count()} items")

    val n = items.count { it.value > 10 }
    println("# of values greater that 10: $n")
}

该示例计算映射对的数量。

val n = items.count { it.value > 10 }

使用count()方法,我们可以计算出大于十的值。

Map has 4 items
Map has 4 items
# of values greater that 10: 3

这是输出。

Kotlin 条目,键,值

Kotlin 映射具有可获取所有条目,键和值的属性。

KotlinEntriesKeysValues.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33)

    println("Entries: " + items.entries)
    println("Keys:" + items.keys)
    println("Values:" + items.values)
}

该示例使用entrieskeysvalues属性。

Entries: [coins=12, books=45, cups=33]
Keys:[coins, books, cups]
Values:[12, 45, 33]

这是输出。

Kotlin mutableMapOf

使用mutableMapOf()创建一个可变映射。

KotlinMutableMap.kt

package com.zetcode

fun main() {

    val user = mutableMapOf("name" to "John Doe", "occupation" to "programmer")
    println(user)

//    user.put("location", "USA")
    user["location"] = "USA"
    println(user)

    user.remove("occupation")
    println(user)

    user.clear()
    println(user)

    if (user.isEmpty()) {
        println("empty")
    } else {
        println("not empty")
    }
}

该示例创建一个可变映射并介绍其方法。

//    user.put("location", "USA")
user["location"] = "USA"
println(user)

新对将添加到映射。 IntelliJ IDEA 建议分配操作。

user.remove("occupation")

remove()删除一对。

user.clear()

clear()删除所有对。

if (user.isEmpty()) {
    println("empty")
} else {
    println("not empty")
}

isEmpty()方法检查映射是否为空。

{name=John Doe, occupation=programmer}
{name=John Doe, occupation=programmer, location=USA}
{name=John Doe, location=USA}
{}
empty

这是输出。

Kotlin 获取值

有几种方法可以从 Kotlin 映射中检索值。

KotlinMapGet.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)

//    println(items.get("coins"))
    println(items["coins"])

    println(items.getValue("coins"))

    println(items.getOrDefault("pens", 0))
    println(items.getOrDefault("pencils", 0))

    val nOfPencils = items.getOrElse("pencils", {
        0
    })

    println(nOfPencils)
}

该示例从映射获取值。

//    println(items.get("coins"))
println(items["coins"])

IntelliJ IDEA 建议使用索引操作代替get()

println(items.getOrDefault("pens", 0))

getOrDefault()返回与键对应的值,或者如果不存在键,则返回指定的默认值。

val nOfPencils = items.getOrElse("pencils", {
    0
})

getOrElse()返回给定键的值,或者如果没有给定键的条目,则返回指定函数的结果。

Kotlin 包含键/值

containsKey()检查映射是否包含键。 containsValue()检查映射是否包含值。

KotlinMapContains.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)

    if (items.containsKey("cups")) {

        println("contains cups")
    } else {

        println("does not contain cups")
    }

    val value = 25

    if (items.containsValue(value)) {

        println("contains value $value")
    } else {

        println("does not contain value $value")
    }
}

该示例检查映射是否包含键"cups"和值 25。

Kotlin 映射遍历

使用forEach(),我们可以遍历映射。

KotlinMapForEach.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)

    items.forEach { (k, v) -> println("There are $v $k") }
}

该示例使用forEach()遍历映射。

There are 12 coins
There are 45 books
There are 33 cups
There are 2 pens

这是输出。

Kotlin 映射过滤器

我们可以使用filterKeys()filterValues()filter()过滤映射。

KotlinMapFilter.kt

package com.zetcode

fun main() {

    val items = mapOf("A" to 90, "B" to 80, "C" to 70, "D" to 60, "E" to 50)

    val filtered = items.filterKeys { it == "A" || it == "C" }
    println(filtered)

    val filtered2 = items.filterValues { it >= 70 }
    println(filtered2)

    val filtered3 = items.filter { it.key == "A" || it.value == 50 }
    println(filtered3)
}

该示例过滤映射。

val filtered = items.filterKeys { it == "A" || it == "C" }

我们过滤出所有与指定键匹配的对。

val filtered2 = items.filterValues { it >= 70 }

我们过滤出所有与指定值匹配的对。

val filtered3 = items.filter { it.key == "A" || it.value == 50 }

在这里,我们过滤出与给定键或值匹配的所有对。

{A=90, C=70}
{A=90, B=80, C=70}
{A=90, E=50}

这是输出。

Kotlin 有序映射

使用sortedMapOf()创建排序的映射。

KotlinSortedMap.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)
    println(items)

    val sortedItems = sortedMapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)
    println(sortedItems)
}

该示例打印未排序和排序的映射。

{coins=12, books=45, cups=33, pens=2}
{books=45, coins=12, cups=33, pens=2}

这些对按键排序。

Kotlin 映射any()

如果至少一个条目与给定谓词匹配,则any()方法返回true

KotlinMapAny.kt

package com.zetcode

fun main() {

    val items = mapOf("coins" to 12, "books" to 45, "cups" to 33, "pens" to 2)

    val value = 12

    val hasValue = items.any { it.value == value }

    if (hasValue) {
        println("The map has value $value")
    } else {
        println("The map does not have value $value")
    }

    val isEven: (Int) -> Boolean = { it % 2 == 0 }

    val hasEvenValue = items.any { isEven(it.value) }

    if (hasEvenValue) {
        println("The map has even value(s)")
    } else {
        println("The map does not have even value(s)")
    }
}

在该示例中,我们检查映射是否包含至少一个值 12,以及是否存在至少一个偶数值。

The map has value 12
The map has even value(s)

这是输出。

在本教程中,我们介绍了 Kotlin 映射。 您可能也对相关的 Kotlin 教程感兴趣: Kotlin 设置教程Kotlin 数组教程或列出所有 Kotlin 教程

Kotlin 集

原文: http://zetcode.com/kotlin/sets/

Kotlin 集教程展示了如何在 Kotlin 中使用集。 集是元素的一般无序集,不允许重复。

Kotlin 区分只读集和可变集。 用setOf()创建只读集,用mutableSetOf()设置可变集。

Kotlin setOf()

setOf()方法在 Kotlin 中创建一个新的只读集。

KotlinSetOf.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = setOf("pen", "cup", "dog", "spectacles")
    println("The set contains ${words.size} elements.")
}

该示例使用setOf()创建一组新单词。 集的大小由size属性确定。

集不能包含重复的元素。

KotlinSetNoDuplicates.kt

package com.zetcode

fun main(args: Array<String>) {

    val words2 = setOf("pen", "cup", "dog", "pen", "spectacles")
    words2.forEach { e -> println(e)}
}

即使我们在setOf()中添加了两支笔,也只有一支笔。

pen
cup
dog
spectacles

这是输出。

Kotlin 集基础知识

在下一个示例中,我们有一个简单的 Kotlin Set示例。

KotlinSetBasic.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2)

    val len = nums.count()
    val max = nums.max()
    val min = nums.min()
    val sum = nums.sum()
    val avg = nums.average()

    val msg = """
               max: $max, min: $min,
               count: $len, sum: $sum,
               average: $avg
              """
    println(msg.trimIndent())
}

该示例创建了一组数字并计算了一些统计信息。

val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2)

使用setOf()函数创建 Kotlin 只读集。

val len = nums.count()
val max = nums.max()
val min = nums.min()
val sum = nums.sum()
val avg = nums.average()

我们计算值的数量,最大值,最小值,总和和平均值。

max: 11, min: 1,
count: 8, sum: 45,
average: 5.625

这是输出。

Kotlin 集索引

集中的每个元素都有一个索引。 Kotlin 集索引从零开始。 最后一个元素的索引为len-1

KotlinSetIndex.kt

package com.zetcode

fun main(args: Array<String&t;) {

    val words = setOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles", "cup", "bread")

    val w1 = words.elementAt(0)
    println(w1)

    val i1 = words.indexOf("cup")
    println("The first index of cup is $i1")

    val i2 = words.lastIndexOf("cup")
    println("The last index of cup is $i2")
}

该示例介绍了 Kotlin Set索引操作。

val w1 = words.elementAt(0)

使用elementAt()方法检索元素。 该方法将要检索的元素的索引作为参数。

val i1 = words.indexOf("cup")

indexOf()返回单词在集中首次出现的索引。

val i2 = words.lastIndexOf("cup")

lastIndexOf()返回该单词在集中最后一次出现的索引。

pen
The first index of cup is 1
The last index of cup is 1

这是输出。

Kotlin 集大小

count()方法返回集中的元素数。

KotlinSetCount.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val len = nums.count()
    println("There are $len elements")

    val size = nums.size
    println("The size of the set is $size")

    val n1 = nums.count { e -> e < 0 }
    println("There are $n1 negative values")

    val n2 = nums.count { e -> e % 2 == 0 }
    println("There are $n2 even values")
}

该示例返回集中值的数量,负值的数量和偶数的数量。

val len = nums.count()
println("There are $len elements")

val size = nums.size
println("The size of the set is $size") 

我们可以使用count()方法或size属性来确定集中元素的数量。

val n1 = nums.count { e -> e < 0 }

count()可以将谓词函数作为参数。 在我们的情况下,它对于小于 0 的值返回true

val n2 = nums.count { e -> e % 2 == 0 }

我们得到集中偶数的数量。

There are 11 elements
The size of the set is 11
There are 3 negative values
There are 5 even values

这是输出。

Kotlin 集第一个和最后一个元素

我们有方法来获取集的第一个和最后一个元素。

KotlinSetFirstLast.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = setOf("pen", "cup", "dog", "person",
            "cement", "coal", "donkey", "spectacles")

    val w1 = words.first()
    println(w1)

    val w2 = words.last()
    println(w2)

    val w3 = words.findLast { w -> w.startsWith('d') }
    println(w3)

    val w4 = words.first { w -> w.startsWith('d') }
    println(w4)
}

该示例创建了一组单词。 我们得到集的第一个和最后一个元素。

val w1 = words.first()

我们用first()获得第一个元素。

val w2 = words.last()

我们用last()获得最后一个元素。

val w3 = words.findLast { w -> w.startsWith('d') }

我们以findLast()检索以'd'开头的集的最后一个元素。

val w4 = words.first { w -> w.startsWith('d') }

我们以first()检索以'd'开头的集的第一个元素。

pen
spectacles
donkey
dog

这是输出。

Kotlin 集迭代

Set迭代或Set循环是一个遍历集元素的过程。

KotlinSetIterate.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = setOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles")

    words.forEach { e -> print("$e ") }
    println()

    for (word in words) {

        print("$word ")
    }

    println()

    for (i in 0 until words.size) {

        print("${words.elementAt(i)} ")
    }

    println()

    words.forEachIndexed({i, e -> println("$i - $e")})

    val it: Iterator<String> = words.asIterable().iterator()

    while (it.hasNext()) {

        val e = it.next()
        print("$e ")
    }

    println()
}

该示例显示了在 Kotlin 中循环播放集的五种方法。

words.forEach { e -> print("$e ") }

forEach()对每个设置的元素执行给定的动作。 我们为它传递了一个匿名函数,该函数将打印当前元素。

for (word in words) {

    print("$word ")
}

我们用for循环设置。 for循环逐个遍历设置的元素; 在每个循环中,word变量指向集中的下一个元素。

for (i in 0 until words.size) {

    print("${words.elementAt(i)} ")
}

另一种for循环利用集的大小。 until关键字创建一系列设置的索引。

words.forEachIndexed({i, e -> println("$i - $e")})

使用forEachIndexed()方法,我们遍历具有每次迭代可用索引和值的集。

val it: Iterator<String> = words.asIterable().iterator()

while (it.hasNext()) {

    val e = it.next()
    print("$e ")
}

最后一种方法是使用Iteratorwhile循环。

pen cup dog person cement coal spectacles 
pen cup dog person cement coal spectacles 
pen cup dog person cement coal spectacles 
0 - pen
1 - cup
2 - dog
3 - person
4 - cement
5 - coal
6 - spectacles
pen cup dog person cement coal spectacles 

这是输出。

Kotlin 集排序

以下示例显示如何在 Kotlin 中对Set值进行排序。 由于使用setOf()创建的集是只读的,因此这些方法不会更改集,而是返回新的修改后的列表。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinSetSorting.kt

package com.zetcode

import com.zetcode.bean.Car

fun main(args: Array<String>) {

    val nums = setOf(11, 5, 3, 8, 1, 9, 6, 2)

    val sortAsc = nums.sorted()
    println(sortAsc)

    val sortDesc = nums.sortedDescending()
    println(sortDesc)

    val revNums = nums.reversed()
    println(revNums)

    val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val res = cars.sortedBy { car -> car.name }
    res.forEach { e -> println(e) }

    println("*************")

    val res2 = cars.sortedByDescending { car -> car.name }
    res2.forEach { e -> println(e) }
}

该示例按升序和降序对集值进行排序,反转集元素,并按名称对汽车对象进行排序。

val sortAsc = nums.sorted()

sorted()方法返回根据自然排序顺序排序的所有元素的列表。

val sortDesc = nums.sortedDescending()

sortedDescending()方法返回所有元素按照其自然排序顺序降序排列的列表。

val revNums = nums.reversed()

reversed()方法返回具有相反顺序元素的列表。

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

我们创建了一组汽车对象。 这些对象可以按名称或价格排序。

val res = cars.sortedBy { car -> car.name }

使用sortedBy(),我们按名称对汽车进行升序排序。

val res2 = cars.sortedByDescending { car -> car.name }

使用sortedByDescending(),我们按名称对汽车进行降序排序。

[1, 2, 3, 5, 6, 8, 9, 11]
[11, 9, 8, 6, 5, 3, 2, 1]
[2, 6, 9, 1, 8, 3, 5, 11]
Car(name=Mazda, price=6300)
Car(name=Mercedes, price=18600)
Car(name=Skoda, price=5670)
Car(name=Toyota, price=12400)
*************
Car(name=Toyota, price=12400)
Car(name=Skoda, price=5670)
Car(name=Mercedes, price=18600)
Car(name=Mazda, price=6300)

这是输出。

Kotlin 集包含

使用contains()方法,我们可以检查集中是否包含指定的元素。

KotlinSetContains.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val r = nums.contains(4)

    if (r) println("The set contains 4")
    else println("The set does not contain 4")

    val r2 = nums.containsAll(setOf(1, -1))

    if (r2) println("The set contains -1 and 1")
    else println("The set does not contain -1 and 1")
}

可以检查一组是否包含一个或多个元素。

val r = nums.contains(4)

在这里,我们检查nums集是否包含 4。该方法返回布尔值。

val r2 = nums.containsAll(setOf(1, -1))

此行检查集是否包含两个值:1 和-1。

The set contains 4
The set contains -1 and 1

这是输出。

Kotlin 可变集

使用mutableSetOf(),我们可以在 Kotlin 中创建可变集。

KotlinListMutable.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = mutableSetOf(3, 4, 5)

    nums.add(6)
    nums.add(7)
    nums.addAll(setOf(8, 9, 10))

    println(nums)

    nums.remove(10)

    println(nums)

    nums.retainAll(setOf(12, 14, 16, 18))

    println(nums)

    nums.clear()

    if (nums.isEmpty()) println("The set is empty")
    else println("The set is not epty")
}

该示例创建一个可变集并介绍其几种方法。

val nums = mutableSetOf(3, 4, 5)

我们创建了三个整数元素的可变集。

nums.add(6)
nums.add(7)
nums.addAll(setOf(8, 9, 10))

add()在集的末尾添加一个新元素。 addAll()在集的末尾添加了多个元素。

nums.clear()

clear()方法从集中删除所有元素。

if (nums.isEmpty()) println("The set is empty")
else println("The set is not epty")

使用isEmpty()方法,我们检查集是否为空。

[3, 4, 5, 6, 7, 8, 9, 10]
[3, 4, 5, 6, 7, 8, 9]
[]
The set is empty

这是输出。

Kotlin 并集

联合操作返回一个集,其中包含两个集中的所有不同元素。

KotlinSetUnion.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(1, 2, 3)
    val nums2 = setOf(3, 4, 5)

    val nums3 = nums.union(nums2)

    println(nums3)
}

在示例中,我们有两组整数。 我们将集与union()方法结合在一起。

[1, 2, 3, 4, 5]

这是输出。

Kotlin 集最大值

以下示例显示如何查找集的最大值。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinSetMax.kt

package com.zetcode

import com.zetcode.bean.Car

fun main(args: Array<String>) {

    val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2)

    println(nums.max())

    val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val car = cars.maxBy { car -> car.price }
    println("The max price is ${car?.price} of ${car?.name}")
}

该示例查找一组整数和一组汽车对象的最大值。

val nums = setOf(11, 5, 23, 8, 1, 9, 6, 2)

println(nums.max())

使用max()可以轻松找到一组整数的最大值。

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

val car = cars.maxBy { car -> car.price }
println("The max price is ${car?.price} of ${car?.name}")

处理对象时,需要指定用于查找最大值的属性。 maxBy()方法具有选择器函数,用于选择汽车的price属性。

23
The max price is 18600 of Mercedes

这是输出。

Kotlin 集过滤器

过滤是一种操作,只有满足某些条件的元素才能通过。

Car.kt

package com.zetcode.bean

data class Car(var name: String, var price: Int)

这是一个Car bean。

KotlinListFilter.kt

package com.zetcode

import com.zetcode.bean.Car

fun main(args: Array<String>) {  

    val words = setOf("pen", "cup", "dog", "person",
            "cement", "coal", "spectacles")

    val words2 = words.filter { e -> e.length == 3 }
    words2.forEach { e -> print("$e ") }

    println()

    val words3 = words.filterNot { e -> e.length == 3 }

    words3.forEach { e -> print("$e ") }

    println()

    val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
            Car("Skoda", 5670), Car("Mercedes", 18600))

    val res = cars.filter { car -> car.price > 10000 }
    res.forEach { e -> println(e) }
}

该示例介绍了对 Kotlin 集的过滤操作。

val words2 = words.filter { e -> e.length == 3 }

filter()方法采用谓词函数作为参数。 谓词给出了元素必须满足的条件。 我们过滤掉长度等于 3 的单词。

val words3 = words.filterNot { e -> e.length == 3 }

filterNot()的作用相反:它允许通过不符合给定条件的元素。

val cars = setOf(Car("Mazda", 6300), Car("Toyota", 12400),
        Car("Skoda", 5670), Car("Mercedes", 18600))

val res = cars.filter { car -> car.price > 10000 }

这些行过滤掉价格大于 10000 的汽车对象。

pen cup dog 
person cement coal spectacles 
Car(name=Toyota, price=12400)
Car(name=Mercedes, price=18600)

这是输出。

Kotlin 集映射

映射操作通过在集的每个元素上应用转换函数来返回修改后的列表。

KotlinListMap.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(1, 2, 3, 4, 5, 6)

    val nums2 = nums.map { e -> e * 2 }
    println(nums2)
}

我们有一组整数。 使用map()方法,我们将每个集元素乘以 2。该方法将重建一个新列表。

[2, 4, 6, 8, 10, 12]

这是示例输出。

Kotlin 集归约

精简是一种终端操作,可将设置值聚合为单个值。 reduce()方法对一个累加器和每个元素(从左到右)应用一个函数,以将其减小为单个值。

KotlinSetReduce.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, 1, 7, 6, 8, 9)

    val sum = nums.reduce { total, next -> total + next }
    println(sum)
}

在示例中,我们对一组整数使用reduce操作。

val sum = nums.reduce { total, next -> total + next }

我们计算值的总和。 total是累加器,next是列表中的下一个值。

45

这是输出。

Kotlin 集折叠

折叠操作类似于缩小操作。 折叠是将设置值聚合为单个值的终端操作。 区别在于折叠从初始值开始。

KotlinSetFold.kt

package com.zetcode

fun main(args: Array<String>) {

    val expenses = setOf(20, 40, 80, 15, 25)

    val cash = 550

    val res = expenses.fold(cash) {total, next -> total - next}
    println(res)
}

我们有一套费用。 这些费用适用于初始可用现金金额。

val res = expenses.fold(cash) {total, next -> total - next}

利用fold(),我们从cash推算出所有费用,并返回剩余值。

370

这是我们减去可用金额的所有费用后的余额。

Kotlin 集分块

有时候,在进行约简时,我们需要处理集中的更多元素。 我们可以使用chunked()方法将集分成列表列表。

KotlinSetChunked.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(1, 2, 3, 4, 5, 6)

    val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }

    println(res)
}

在示例中,我们有一组六个值。 我们要实现以下操作:1*2 + 3*4 + 5*6。 为此,我们需要将列表分成两个值的块。

val res = nums.chunked(2).fold(0) { total, next -> total + next[0] * next[1] }

我们将集拆分为两个元素的列表,然后对其进行折叠。 next是我们可以在其中使用索引操作的列表。

44

这是示例的输出。

Kotlin 集分区

分区操作将原始集拆分为成对的列表。 第一个列表包含其指定谓词产生true的元素,而第二个列表包含其谓词产生false的元素。

KotlinSetPartition.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, -5, 3, 2, -1, 7, -6, 8, 9)

    val (nums2, nums3) = nums.partition { e -> e < 0 }

    println(nums2)
    println(nums3)
}

我们有一组整数。 使用partition()方法,我们将集分为两个子列表: 一个包含负值,另一个包含正值。

val (nums2, nums3) = nums.partition { e -> e < 0 }

使用解构声明,我们将集一次性分成两部分。

[-5, -1, -6]
[4, 3, 2, 7, 8, 9]

这是输出。

Kotlin 集分组

groupBy()方法通过给定选择器函数返回的键将原始元素集应用于每个元素。 它返回一个映射,其中每个组键都与对应元素的列表相关联。

KotlinSetGroupBy.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8)

    val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" }
    println(res)

    val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles")

    val res2 = words.groupBy { it.length }
    println(res2)
}

该示例显示了如何使用groupBy()方法。

val nums = setOf(1, 2, 3, 4, 5, 6, 7, 8)

val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" }
println(res)

这些行创建了一个映射,该映射具有两个键:"even""odd""even"指向偶数值列表,"odd"指向奇数值列表。

val words = setOf("as", "pen", "cup", "doll", "my", "dog", "spectacles")

val res2 = words.groupBy { it.length }

在这里,我们创建一个带有整数键的映射。 每个关键字将具有一定长度的单词分组。

{odd=[1, 3, 5, 7], even=[2, 4, 6, 8]}
{2=[as, my], 3=[pen, cup, dog], 4=[doll], 10=[spectacles]}

这是输出。

any()

如果至少一个元素与给定的谓词函数匹配,则any()方法返回true

KotlinSetAny.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9)

    val r = nums.any { e -> e > 10 }
    if (r) println("There is a value greater than ten")
    else println("There is no value greater than ten")

    val r2 = nums.any { e -> e < 0 }
    if (r2) println("There is a negative value")
    else println("There is no negative value")

该示例显示any()的用法。

val r2 = nums.any { e -> e < 0 }

在这里,我们检查该集是否包含至少一个负值。 该方法返回一个布尔值。

all()

如果所有元素都满足给定的谓词函数,则all()返回true

KotlinSetAll.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, -1, 7, 6, 8, 9)
    val nums2 = setOf(-3, -4, -2, -5, -7, -8)

    // testing for positive only values
    val r = nums.all { e -> e > 0 }

    if (r) println("nums set contains only positive values")
    else println("nums set does not contain only positive values")

    // testing for negative only values
    val r2 = nums2.all { e -> e < 0 }

    if (r2) println("nums2 set contains only negative values")
    else println("nums2 set does not contain only negative values")
}

该示例显示all()的用法。

// testing for positive only values
val r = nums.all { e -> e > 0 }

在这里,我们测试nums集是否仅包含正值。

Kotlin 集删除

通过放置操作,我们从集中排除了一些元素。

KotlinSetDrop.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val nums2 = nums.drop(3)
    println(nums2)

    val nums3 = nums.sorted().dropWhile { e -> e < 0 }
    println(nums3)

    val nums4 = nums.sorted().dropLastWhile { e -> e > 0 }
    println(nums4)
}

该示例显示了不同放置操作的用法。

val nums2 = nums.drop(3)

使用drop()方法,我们排除了前三个元素。

val nums3 = nums.sorted().dropWhile { e -> e < 0 }

使用dropWhile()方法,我们排除了满足给定谓词函数的前 n 个元素。

val nums4 = nums.sorted().dropLastWhile { e -> e > 0 }

使用dropLastWhile()方法,我们排除了满足给定谓词函数的最后 n 个元素。

[2, 1, -1, 7, 6, -8, 9, -12]
[1, 2, 3, 4, 5, 6, 7, 9]
[-12, -8, -1]

这是输出。

Kotlin 集提取

提取操作是放置操作的补充。 take方法通过选择一些集元素形成一个新列表。

KotlinSetTake.kt

package com.zetcode

fun main(args: Array<String>) {

    val nums = setOf(4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12)

    val nums2 = nums.take(3)
    println(nums2)

    val nums3 = nums.sorted().take(3)
    println(nums3)

    val nums4 = nums.takeWhile { e -> e > 0 }
    println(nums4)

    val nums5 = nums.sortedDescending().takeWhile { e -> e > 0 }
    println(nums5)

    val nums6 = nums.takeIf { e -> e.contains(6) }
    println(nums6)
}

该示例显示了各种take方法的用法。

val nums2 = nums.take(3)

take()方法创建一个具有原始集的前三个元素的新列表。

val nums4 = nums.takeWhile { e -> e > 0 }

takeWhile()采用满足谓词函数的前 n 个元素。

val nums6 = nums.takeIf { e -> e.contains(6) }

如果满足谓词函数中的条件,则takeIf()方法将使用集的所有元素。

[4, 5, 3]
[-12, -8, -1]
[4, 5, 3, 2, 1]
[9, 7, 6, 5, 4, 3, 2, 1]
[4, 5, 3, 2, 1, -1, 7, 6, -8, 9, -12]

这是输出。

在本教程中,我们介绍了 Kotlin 集。 您可能也对相关教程感兴趣: Kotlin 列表教程Kotlin 字符串教程Kotlin 数组教程Kotlin 范围教程Kotlin 变量教程Kotlin 控制流Kotlin 读取文件教程Kotlin 写入文件教程

Kotlin 控制流程

原文: http://zetcode.com/kotlin/controlflow/

Kotlin 控制流教程展示了如何使用ifwhenwhilefor在 Kotlin 程序中进行控制流。

Kotlin 是在 Java 虚拟机上运行的静态类型的编程语言。

Kotlin 由 JetBrains 创建。 Kotlin 是一种面向对象的函数式编程语言。 Kotlin 被设计为一种务实,简洁,安全且可互操作的编程语言。

Kotlin if条件

if关键字用于创建简单的条件测试。 可以与else关键字结合使用。

kotlin_if.kt

package com.zetcode

fun main() {

    print("Enter your age: ")

    val s_age: String? = readLine()

    if (s_age!!.isEmpty()) return

    val age:Int = s_age.toInt()

    if (age > 18) {

        println("You can obtain a driving licence")
    } else {

        println("You cannot obtain a driving licence")
    }
}

在示例中,我们提示输入用户的年龄。 我们读取该值,将其转换为整数,然后存储在变量中。

if (age > 18) {

    println("You can obtain a driving licence")
} else {

    println("You cannot obtain a driving licence")
}

此条件测试年龄是否大于 18 岁。

Kotlin

可以使用if else if语法创建条件的多个分支。

ifelseif.kt

package com.zetcode

fun main() {

    val a = 34
    val b = 43

    if (a == b) {

        println("$a and $b are equal")
    } else if (a < b) {

        println("$a is less than $b")
    } else {

        println("$b is less than $a")
    }
}

在示例中,我们使用if else if来确定两个值是否相等或更大或更小。

Kotlin if表达式

Kotlin 的if是一个表达式,即它返回一个值。

if_expression.kt

package com.zetcode

fun main() {

    val a = 34
    val b = 43

    val max = if (a > b) a else b

    println("max of $a and $b is $max")
}

该示例使用if表达式返回两个值中的最大值。

when表达式

Kotlin 的when表达式用于评估多个条件。 它是 Java switch语句的更强大版本。

when关键字将其参数顺序与所有分支匹配,直到满足某些分支条件为止。 它既可以用作表达式也可以用作语句。

when_expression.kt

package com.zetcode

import java.util.Random

fun main() {

    val r:Int = Random().nextInt(10) - 5

    when {
        r < 0 -> println("negative value")
        r == 0 -> println("zero")
        r > 0 -> println("positive value")
    }
}

在示例中,我们生成一个随机数。 基于随机值,我们将消息打印到控制台。

Kotlin while循环

while关键字用于创建循环。 它运行直到满足给定条件。

while_loop.kt

package com.zetcode

fun main() {

    var i:Int = 0

    while(i < 10) {

        i++
        println("i is $i")
    }

    println(i)
}

该示例使用while循环从一到十打印值。

while(i < 10) {

只要i变量小于 10,就一直在运行while条件。

Kotlin for循环

使用 Kotlin 的for循环,我们可以创建比while更容易创建的循环。

for_loop.kt

package com.zetcode

fun main() {

    val seasons = arrayOf("Spring", "Summer", "Autumn", "Winter")

    for (season in seasons) {

        println(season)
    }

    for (i in 1..15) println(i)
}

在示例中,我们使用for关键字对字符串数组和整数范围进行迭代。

在本教程中,我们介绍了 Kotlin 中的控制流。 您可能也对相关教程感兴趣: Kotlin 字符串教程Kotlin 数组教程或列出所有 Kotlin 教程

Kotlin 写入文件

原文: http://zetcode.com/kotlin/writefile/

Kotlin 写入文件教程展示了如何在 Kotlin 中写入文件。

Kotlin 是一种在 Java 虚拟机上运行的静态类型的编程语言。

本教程提供了四个示例,这些示例可以写入 Kotlin 中的文件。

Kotlin 使用PrintWriter写入文件

PrintWriter将格式化的对象表示形式打印到文本输出流。

writefile.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/myfile.txt"
    val myfile = File(fileName)

    myfile.printWriter().use { out ->

        out.println("First line")
        out.println("Second line")
    }

    println("Writed to file")
}

该示例使用PrintWriter将两行写入文件。

val fileName = "src/resources/myfile.txt"

我们写入src/resources/myfile.txt文件。

myfile.printWriter().use { out ->

printWriter()返回用于将内容写入文件的PrintWriteruse()方法在文件上执行给定的块函数,然后将其关闭。

out.println("First line")
out.println("Second line")

使用println(),我们向文件写入一个字符串,其中包括一个换行符。

Kotlin 使用BufferedWriter写入文件

BufferedWriter将文本写入字符输出流,缓冲字符以更有效地写入单个字符,数组和字符串。

writefile2.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/myfile.txt"
    val myfile = File(fileName)

    myfile.bufferedWriter().use { out ->

        out.write("First line\n")
        out.write("Second line\n")
    }

    println("Writed to file")
}

该示例使用BufferedWriter将两行写入文件。

myfile.bufferedWriter().use { out ->

bufferedWriter()返回用于将内容写入文件的BufferedWriteruse()方法在文件上执行给定的块函数,然后将其关闭。

Kotlin 使用writeText写入文件

writeText()是 Kotlin File扩展函数,可将使用 UTF-8 或其他字符集编码的文本写入文件。 如果该文件存在,它将被覆盖。

writefile3.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/myfile3.txt"
    val myfile = File(fileName)

    val content = "Today snow is falling."

    myfile.writeText(content)

    println("Writed to file")
}

该示例写入具有 Kotlin writeText()扩展函数的文件。

Kotlin 使用writeText写入文件

Files.write()将字节写入文件。

writefile4.kt

package com.zetcode

import java.io.File
import java.nio.file.Files
import java.nio.file.StandardOpenOption

fun main(args: Array<String>) {

    val fileName = "src/resources/myfile.txt"
    val myfile = File(fileName)

    val content = "Today snow is falling.\n"

    Files.write(myfile.toPath(), content.toByteArray(), StandardOpenOption.APPEND)
}

该示例写入具有 Kotlin Files.write()扩展函数的文件。

Files.write(myfile.toPath(), content.toByteArray(), StandardOpenOption.APPEND)

Files.write()的第一个参数是文件的Path,第二个是要写入的字节数组,第三个参数是指定如何打开文件的选项。

在本教程中,我们展示了如何在 Kotlin 中写入文件。 您可能也对相关教程感兴趣: Kotlin 阅读文件教程Kotlin Hello World 教程

Kotlin 读取文件教程

原文: http://zetcode.com/kotlin/readfile/

Kotlin 读取文件教程显示了如何在 Kotlin 中读取文件。 我们展示了几种在 Kotlin 中读取文件的方法。

在本教程中,我们使用File方法读取文件。

本教程提供了五个示例,这些示例在 Kotlin 中读取文件。

thermopylae.txt

The Battle of Thermopylae was fought between an alliance of Greek city-states, 
led by King Leonidas of Sparta, and the Persian Empire of Xerxes I over the 
course of three days, during the second Persian invasion of Greece. 

在示例中,我们使用此文本文件。

Kotlin 使用File.readLines读取文件

File.readLines()读取文件内容为行列表。 不应将其用于大文件。

readfile.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/thermopylae.txt"

    val lines: List<String> = File(fileName).readLines()

    lines.forEach { line -> println(line) }
}

该示例使用File.readLines()读取文件。

Kotlin 使用File.useLines读取文件

File.useLines()读取所有数据作为行列表,并将其提供给回调。 最后关闭读者。

readfile2.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/thermopylae.txt"

    val myList = mutableListOf<String>()

    File(fileName).useLines { lines -> myList.addAll(lines) }

    myList.forEachIndexed { i, line -> println("${i}: " + line) }
}

该示例读取文件并将其打印到控制台。 我们在输出中添加行号。

val myList = mutableListOf<String>()

可变列表已创建。

File(fileName).useLines { lines -> myList.addAll(lines) }

使用File.useLines(),我们将行列表复制到上面创建的可变列表中。

myList.forEachIndexed { i, line -> println("${i}: " + line) }

使用forEachIndexed(),我们为每行添加一个行号。

Kotlin 使用File.readText读取文件

File.readText()String的形式获取此文件的全部内容。 不建议在大文件上使用此方法。

readfile3.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/thermopylae.txt"

    val content = File(fileName).readText()

    println(content)
}

在示例中,我们将整个文件读入一个字符串并将其打印到控制台。

Kotlin 使用InputStream读取文件

InputStream是字节的输入流。

readfile4.kt

package com.zetcode

import java.io.File
import java.io.InputStream
import java.nio.charset.Charset

fun main(args: Array<String>) {

    val fileName = "src/resources/thermopylae.txt"
    val myFile = File(fileName)

    var ins: InputStream = myFile.inputStream()

    var content = ins.readBytes().toString(Charset.defaultCharset())
    println(content)
}

该示例从File创建InputStream并从中读取字节。 字节转换为文本。

var ins: InputStream = myFile.inputStream()

FileinputStream()创建一个InputStream

var content = ins.readBytes().toString(Charset.defaultCharset())

我们使用readBytes()InputStream读取字节,然后使用toString()将字节转换为文本。

Kotlin 使用readBytes读取文件

readBytes()以字节数组的形式读取文件的全部内容。 不建议在大文件上使用。

readfile5.kt

package com.zetcode

import java.io.File

fun main(args: Array<String>) {

    val fileName = "src/resources/thermopylae.txt"
    val file = File(fileName)

    var bytes: ByteArray = file.readBytes()

    bytes.forEachIndexed { i, byte -> (

        if (i == 0) {

            print("${byte} ")
        } else if (i % 10 == 0) {

            print("${byte} \n")
        } else {

            print("${byte} ")
        })
    }    
}

该示例将文本文件读入字节数组。 它将文件以数字形式打印到控制台。

在本教程中,我们展示了如何在 Kotlin 中读取文件。 您可能也对相关教程感兴趣: Kotlin 编写文件教程Kotlin Hello World 教程

Kotlin 正则表达式

原文: http://zetcode.com/kotlin/regularexpressions/

Kotlin 正则表达式教程展示了如何在 Kotlin 中使用正则表达式。

正则表达式用于文本搜索和更高级的文本操作。 正则表达式是内置工具,如grepsed,文本编辑器(如 vi,emacs)以及包括 Kotlin,JavaScript,Perl 和 Python 在内的编程语言。

Kotlin 正则表达式

在 Kotlin 中,我们使用Regex构建正则表达式。

Regex("book")
"book".toRegex()
Regex.fromLiteral("book")

模式是一个正则表达式,用于定义我们正在搜索或操纵的文本。 它由文本文字和元字符组成。 元字符是控制正则表达式计算方式的特殊字符。 例如,使用\s,我们搜索空白。

特殊字符必须双转义,否则我们可以使用 Kotlin 原始字符串。

创建模式后,可以使用其中一个函数将模式应用于文本字符串。 函数包括matches()containsMatchIn()find()findall()replace()split()

下表显示了一些常用的正则表达式:

正则表达式 含义
. 匹配任何单个字符。
? 一次匹配或根本不匹配前面的元素。
+ 与前面的元素匹配一次或多次。
* 与前面的元素匹配零次或多次。
^ 匹配字符串中的起始位置。
` 正则表达式
--- ---
. 匹配任何单个字符。
? 一次匹配或根本不匹配前面的元素。
+ 与前面的元素匹配一次或多次。
* 与前面的元素匹配零次或多次。
^ 匹配字符串中的起始位置。
匹配字符串中的结束位置。
| 备用运算符。
[abc] 匹配abc
[a-c] 范围; 匹配abc
[^abc] 否定,匹配除abc之外的所有内容。
\s 匹配空白字符。
\w 匹配单词字符; 等同于[a-zA-Z_0-9]

Kotlin containsMatchIn方法

如果正则表达式与整个输入字符串匹配,则matches()方法返回truecontainsMatchIn()方法指示正则表达式是否可以在指定的输入中找到至少一个匹配项。

KotlinRegexSimple.kt

package com.zetcode

fun main(args : Array<String>) {

    val words = listOf("book", "bookworm", "Bible",
            "bookish","cookbook", "bookstore", "pocketbook")

    val pattern = "book".toRegex()

    println("*********************")
    println("containsMatchIn function")

    words.forEach { word ->
        if (pattern.containsMatchIn(word)) {
            println("$word matches")
        }
    }

    println("*********************")
    println("matches function")

    words.forEach { word ->
        if (pattern.matches(word)) {
            println("$word matches")
        }
    }
}

在示例中,我们使用matches()containsMatchIn()方法。 我们有一个单词表。 模式将使用这两种方法在每个单词中寻找一个"book"字符串。

val pattern = "book".toRegex()

使用toRegex()方法创建正则表达式模式。 正则表达式由四个普通字符组成。

words.forEach { word ->
    if (pattern.containsMatchIn(word)) {
        println("$word matches")
    }
}

我们遍历列表,并对每个单词应用containsMatchIn()

words.forEach { word ->
    if (pattern.matches(word)) {
        println("$word matches")
    }
}

我们再次遍历该列表,并对每个单词应用matches()

*********************
containsMatchIn function
book matches
bookworm matches
bookish matches
cookbook matches
bookstore matches
pocketbook matches
*********************
matches function
book matches

对于containsMatchIn()方法,如果"book"单词在单词中某处,则模式匹配; 对于matches(),输入字符串必须完全匹配模式。

Kotlin `find()方法

find()方法返回输入中正则表达式的第一个匹配项,从指定的起始索引开始。 起始索引默认为 0。

KotlinRegexFind.kt

package com.zetcode

fun main(args : Array<String>) {

    val text = "I saw a fox in the wood. The fox had red fur."

    val pattern = "fox".toRegex()

    val found = pattern.find(text)

    val m = found?.value
    val idx = found?.range

    println("$m found at indexes: $idx")

    val found2 = pattern.find(text, 11)

    val m2 = found2?.value
    val idx2 = found2?.range

    println("$m2 found at indexes: $idx2")
}

在示例中,我们找到了"fox"项匹配项的索引。

val found = pattern.find(text)

val m = found?.value
val idx = found?.range

我们找到"fox"一词的第一个匹配项。 我们得到它的值和索引。

val found2 = pattern.find(text, 11)

val m2 = found2?.value
val idx2 = found2?.range

在第二种情况下,我们从索引 11 开始搜索,从而找到下一项。

fox found at indexes: 8..10
fox found at indexes: 29..31

这是输出。

Kotlin findAll方法

findAll()方法返回输入字符串中所有出现的正则表达式的序列。

KotlinFindAll.kt

package com.zetcode

fun main(args : Array<String>) {

    val text = "I saw a fox in the wood. The fox had red fur."

    val pattern = "fox".toRegex()

    val found = pattern.findAll(text)

    found.forEach { f ->
        val m = f.value
        val idx = f.range
        println("$m found at indexes: $idx")
     }
}

在示例中,我们使用findAll()查找所有出现的'fox'术语。

Kotlin split()方法

split()方法将输入字符串拆分为正则表达式的匹配项。

KotlinRegexSplitting.js

package com.zetcode

fun main(args: Array<String>) {

    val text = "I saw a fox in the wood. The fox had red fur."

    val pattern = "\\W+".toRegex()

    val words = pattern.split(text).filter { it.isNotBlank() }

    println(words)
}

在示例中,我们找出"fox"项的出现次数。

val pattern = "\\W+".toRegex()

该模式包含\W命名的字符类,代表非单词字符。 与+量词结合使用时,该模式会查找非单词字符,例如空格,逗号或点,这些字符通常用于分隔文本中的单词。 请注意,字符类是两次转义的。

val words = pattern.split(text).filter { it.isNotBlank() }

使用split()方法,我们将输入字符串分成单词列表。 此外,我们删除了空白的结尾词,该词是由于我们的文本以非单词字符结尾而创建的。

[I, saw, a, fox, in, the, wood, The, fox, had, red, fur]

这是输出。

不区分大小写的匹配

为了启用不区分大小写的搜索,我们将RegexOption.IGNORE_CASE传递给toRegex()方法。

KotlinRegexCaseInsensitive.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("dog", "Dog", "DOG", "Doggy")

    val pattern = "dog".toRegex(RegexOption.IGNORE_CASE)

    words.forEach { word ->
        if (pattern.matches(word)) {
            println("$word matches")

        }
    }
}

在示例中,无论大小写如何,我们都将模式应用于单词。

val pattern = "dog".toRegex(RegexOption.IGNORE_CASE)

我们使用RegexOption.IGNORE_CASE忽略输入字符串的大小写。

dog matches
Dog matches
DOG matches

这是输出。

点元字符

点(。)元字符代表文本中的任何单个字符。

KotlinRegexDotMeta.kt

package com.zetcode

fun main(args : Array<String>) {

    val words = listOf("seven", "even", "prevent", "revenge", "maven",
            "eleven", "amen", "event")

    val pattern = "..even".toRegex()

    words.forEach { word ->
        if (pattern.containsMatchIn(word)) {
            println("$word matches")

        }
    }
}

在示例中,列表中有八个单词。 我们在每个单词上应用一个包含两个点元字符的模式。

prevent matches
eleven matches

有两个与模式匹配的单词。

问号元字符

问号(?)元字符是与上一个元素零或一次匹配的量词。

KotlinRegexQMarkMeta.kt

package com.zetcode

fun main(args : Array<String>) {

    val words = listOf("seven", "even", "prevent", "revenge", "maven",
            "eleven", "amen", "event")

    val pattern = ".?even".toRegex()

    words.forEach { word ->
        if (pattern.matches(word)) {
            println("$word matches")

        }
    }
}

在示例中,我们在点字符后添加问号。 这意味着在模式中我们可以有一个任意字符,也可以在那里没有任何字符。

seven matches
even matches

这是输出。

{n,m}量词

{n,m}量词至少匹配前一个表达式的n个,最多匹配m个。

KotlinRegexMnQuantifier.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("pen", "book", "cool", "pencil", "forest", "car",
            "list", "rest", "ask", "point", "eyes")

    val pattern = "\\w{3,4}".toRegex()

    words.forEach { word ->
        if (pattern.matches(word)) {

            println("$word matches")
        } else {
            println("$word does not match")
        }
    }
}

在示例中,我们搜索具有三个或四个字符的单词。

val pattern = "\\w{3,4}".toRegex()

在模式中,我们将一个单词字符重复三到四次。 请注意,数字之间不能有空格。

pen matches
book matches
cool matches
pencil does not match
forest does not match
car matches
list matches
rest matches
ask matches
point does not match
eyes matches

这是输出。

锚点

锚点匹配给定文本内字符的位置。 当使用^锚时,匹配必须发生在字符串的开头,而当使用$锚时,匹配必须发生在字符串的结尾。

KotlinRegexAnchors.kt

package com.zetcode

fun main(args : Array<String>) {

    val sentences = listOf("I am looking for Jane.",
        "Jane was walking along the river.",
        "Kate and Jane are close friends.")

    val pattern = "^Jane".toRegex()

    sentences.forEach { sentence ->
        if (pattern.containsMatchIn(sentence)) {
            println("$sentence")

        }
    }
}

在示例中,我们有三个句子。 搜索模式为^Jane。 该模式检查"Jane"字符串是否位于文本的开头。 Jane\.将在句子结尾处查找"Jane"

交替

交替运算符| 创建具有多种选择的正则表达式。

KotlinRegexAlternations.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("Jane", "Thomas", "Robert",
            "Lucy", "Beky", "John", "Peter", "Andy")

    val pattern = "Jane|Beky|Robert".toRegex()

    words.forEach { word ->

        if (pattern.matches(word)) {

            println("$word")
        }
    }
}

列表中有八个名称。

val pattern = "Jane|Beky|Robert".toRegex()

此正则表达式查找Jane"Beky""Robert"`字符串。

子模式

子模式是模式中的模式。 子模式使用()字符创建。

KotlinRegexSubpatterns.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("book", "bookshelf", "bookworm",
            "bookcase", "bookish", "bookkeeper", "booklet", "bookmark")

    val pattern = "book(worm|mark|keeper)?".toRegex()

    words.forEach { word ->

        if (pattern.matches(word)) {

            println("$word matches")
        } else {

            println("$word does not match")
        }
    }
}

该示例创建一个子模式。

val pattern = "book(worm|mark|keeper)?".toRegex()

正则表达式使用子模式。 它与书呆子,书签,簿记员和书本单词匹配。

book matches
bookshelf does not match
bookworm matches
bookcase does not match
bookish does not match
bookkeeper matches
booklet does not match
bookmark matches

这是输出。

字符类

字符类定义了一组字符,任何字符都可以出现在输入字符串中以使匹配成功。

KotlinRegexChClass.kt

package com.zetcode

fun main(args: Array<String>) {

    val words = listOf("a gray bird", "grey hair", "great look")

    val pattern = "gr[ea]y".toRegex()

    words.forEach { word ->

        if (pattern.containsMatchIn(word)) {

            println("$word")
        }
    }
}

在该示例中,我们使用字符类同时包含灰色和灰色单词。

val pattern = "gr[ea]y".toRegex()

[ea]类允许在模式中使用'e'或'a'字符。

命名字符类

有一些预定义的字符类。 \s与空白字符[\t\n\t\f\v]匹配,\d与数字[0-9]匹配,\w与单词字符[a-zA-Z0-9_]匹配。

KotlinRegexNamedClass.kt

package com.zetcode

fun main(args: Array<String>) {

    val text = "We met in 2013\. She must be now about 27 years old."

    val pattern = "\\d+".toRegex()
    val found = pattern.findAll(text)

    found.forEach { f ->
        val m = f.value
        println("$m")
    }
}

在示例中,我们在文本中搜索数字。

val pattern = "\\d+".toRegex()

\d+模式在文本中查找任意数量的数字集。

val found = pattern.findAll(text) 

findAll()查找所有匹配项。

2013
27

这是输出。

捕获组

捕获组是一种将多个字符视为一个单元的方法。 通过将字符放置在一组圆括号内来创建它们。 例如,(book)是包含'b', 'o', 'o', 'k'字符的单个组。

捕获组技术使我们能够找出字符串中与正则表达式模式匹配的那些部分。

KotlinRegexCapturingGroups.kt

package com.zetcode

fun main(args: Array<String>) {

    val content = """<p>The <code>Pattern</code> is a compiled
representation of a regular expression.</p>"""

    val pattern = "(<\\/?[a-z]*>)".toRegex()

    val found = pattern.findAll(content)

    found.forEach { f ->
        val m = f.value
        println("$m")
    }
}

该代码示例通过捕获一组字符来打印提供的字符串中的所有 HTML 标签。

val found = pattern.findAll(content)

为了找到所有标签,我们使用findAll()方法。

<p>
<code>
</code>
</p>

我们找到了四个 HTML 标签。

Kotlin 正则表达式电子邮件示例

在以下示例中,我们创建一个用于检查电子邮件地址的正则表达式模式。

KotlinRegexEmails.kt

package com.zetcode

fun main(args: Array<String>) {

    val emails = listOf("luke@gmail.com", "andy@yahoocom",
            "34234sdfa#2345", "f344@gmail.com", "dandy!@yahoo.com")

    val pattern = "[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\\.[a-zA-Z.]{2,18}".toRegex()

    emails.forEach { email ->

        if (pattern.matches(email)) {

            println("$email matches")
        } else {

            println("$email does not match")
        }
    }
}

本示例提供了一种可能的解决方案。

val pattern = "[a-zA-Z0-9._-]+@[a-zA-Z0-9-]+\\.[a-zA-Z.]{2,18}".toRegex()

电子邮件分为五个部分。 第一部分是本地部分。 通常,它是公司名称,个人名称或昵称。 [a-zA-Z0-9._-]+列出了我们可以在本地部分使用的所有可能的字符。 它们可以使用一次或多次。

第二部分由文字@字符组成。 第三部分是领域部分。 通常是电子邮件提供商的域名,例如 yahoo 或 gmail。 [a-zA-Z0-9-]+是一个字符类,提供可在域名中使用的所有字符。 +量词允许使用这些字符中的一个或多个。

第四部分是点字符。 它前面是双转义字符(\)以获取文字点。

最后一部分是顶级域名:[a-zA-Z.]{2,18}。 顶级域可以包含 2 到 18 个字符,例如sk, net, info, travel, cleaning, travelinsurance最大长度可以为 63 个字符,但是今天大多数域都少于 18 个字符。 还有一个点字符。 这是因为某些顶级域包含两个部分: 例如co.uk

luke@gmail.com matches
andy@yahoocom does not match
34234sdfa#2345 does not match
f344@gmail.com matches
dandy!@yahoo.com does not match

这是输出。

在本章中,我们介绍了 Kotlin 中的正则表达式。

您可能也对以下相关教程感兴趣: Kotlin 范围教程Kotlin 设置教程

posted @ 2024-10-24 18:16  绝不原创的飞龙  阅读(18)  评论(0编辑  收藏  举报