preface
This article mainly explains higher-order functions, inline functions, several useful higher-order functions, set transformation and sequence, SAM transformation, case: count the number of characters, case: HTML DSL, practice: Experience Gradle Kotlin DSL
List of Kotlin articles
List of Kotlin articles: Click here to jump to see
directory
(1) Higher-order functions
(1) The definition of higher-order functions
A function whose parameter type contains a function type or whose return value type is a function type is a higher-order function
fun needsFunction(block: () -> Unit) {
block()
}
fun returnsFunction(a): () - >Long {
return { System.currentTimeMillis() }
}
Copy the code
(2) Call of higher-order functions
public inline fun IntArray.forEach(action: (Int) - >Unit): Unit {
for (element in this) action(element)
}
Copy the code
Call:
val intArray = IntArray(5){ it + 1 }
intArray.forEach {
println(it)
}
intArray.forEach(::println)
intArray.forEach {
println("Hello $it")}Copy the code
fun main(a) {
cost {
val fibonacciNext = fibonacci()
for (i in 0.10.) {
println(fibonacciNext())
}
}
}
fun cost(block: () -> Unit) {
val start = System.currentTimeMillis()
block()
println("${System.currentTimeMillis() - start}ms")}fun fibonacci(a): () - >Long {
var first = 0L
var second = 1L
return {
val next = first + second
val current = first
first = second
second = next
current
}
}
Copy the code
Results:
0
1
1
2
3
5
8
13
21
34
55
7ms
Copy the code
(2) inline function
(1) Definition of inline function
A function marked inline is an inline function, which is replaced at compile time with the body of the function’s method where the function is called
val ints = intArrayOf(1.2.3.4)
ints.forEach { // forEach is an inline function, where the code should be replaced with the body of the method inside forEach, i.e. the for loop
println("Hello $it")}// forEach is an inline function
public inline fun IntArray.forEach(crossinline action: (Int) - >Unit): Unit {
for (element in this) action(element)
}
// The above code can be written as follows
val ints = intArrayOf(1.2.3.4)
for (element in ints) {
println("Hello $element")}Copy the code
(2) Return of the inline function
val ints = intArrayOf(1.2.3.4)
ints.forEach {
if (it == 3) return@forEach // Only it == 3 is not executed, jumping out of this inline function call
println("Hello $it")}// Equivalent to the above code
for (element in ints) {
if (element == 3) continue
println("Hello $element")}Copy the code
Results:
Hello 1
Hello 2
Hello 4
Hello 1
Hello 2
Hello 4
Copy the code
(3) The non-local return of the inline function
inline fun nonLocalReturn(block: () -> Unit) {
block()
}
nonLocalReturn {
return // Returns from an external function} such as:fun main(a) {
nonLocalReturn {
return // Return from main}}Copy the code
inline fun Runnable(block: () -> Unit): Runnable {
return object : Runnable {
override fun run(a) {
block()
}
}
}
// There may be an invalid non-local return because the block is not called in the same call context as the definition
Copy the code
Improved: add noinline to prevent function arguments from being inlined
inline fun Runnable(noinline block: () -> Unit): Runnable {
return object : Runnable {
override fun run(a) {
block()
}
}
}
Copy the code
(4) Inline attributes
var pocket: Double = 0.0
var money: Double
inline get() = pocket
inline set(value) {
pocket = value
}
Copy the code
After compiling:
(5) Limitation of inline function
Public /protected inline methods can only access the corresponding class’s public members. Inline function arguments cannot be stored (assigned to variables). Inline function arguments can only be passed to other inline function arguments
(3) several useful higher-order functions
(1) An introduction to several useful higher-order functions
(2) Use of several useful higher-order functions
import java.io.File
class Person(var name: String, var age: Int)
fun main(a) {
val person = Person("benny".20)
person.let(::println)
person.run(::println)
val person2 = person.also {
it.name = "hhh"
}
val person3 = person.apply {
name = "xxx"
}
File("build.gradle").inputStream().reader().buffered()
.use {
println(it.readLines())
}
}
Copy the code
(4) Set transformation and sequence
(1) For I…
Java:
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
Copy the code
Kotlin:
for (i in 0.10.) {
println(i)
}
Copy the code
(2) the forEach
Java:
list.forEach((e) -> {
System.out.println(e);
});
list.forEach((e) -> {
if (e == 2) return;
System.out.println(e);
});
Copy the code
Kotlin:
list.forEach {
println(it);
}
list.forEach {
if (it == 2) {
return@forEach
}
println(it)
}
Copy the code
Note that forEach cannot continue or break
(3) Examples of mapping operations for collections
(4) Filter operation
The elements that meet the conditions are retained to form a new setJava:
list.stream()
.filter(e -> e % 2= =0)
.forEach(System.out::println);
Copy the code
Kotlin:
list.filter { it % 2= =0 }
list.asSequence()
.filter { it % 2= =0 }
Copy the code
(5) Map operation
After some transformation, it becomes another set
Java:
list.stream()
.map(e -> e * 2 + 1);
Copy the code
Kotlin:
list.asSequence()
.map { it * 2 + 1 }
Copy the code
Integrated applets: Java:
public class JavaStreams {
public static void main(String... args) {
var list = new ArrayList<Integer>();
list.addAll(Arrays.asList(1.2.3.4));
list.stream()
.filter(e -> {
System.out.println("filter: " + e); // if 1,3 does not meet the requirements, direct output; if 2,4 do not meet the requirements, proceed down
return e % 2= =0;
})
.map(e -> {
System.out.println("map: " + e);
return e * 2 + 1;
})
.forEach(e -> {
System.out.println("forEach: "+ e); }); }}Copy the code
Results:
filter: 1
filter: 2
map: 2
forEach: 5
filter: 3
filter: 4
map: 4
forEach: 9
Copy the code
Kotlin:
fun main(a) {
val list = listOf(1.2.3.4)
list.asSequence()
.filter {
println("filter: $it")
it % 2= =0
}.map {
println("map: $it")
it * 2 + 1
}.forEach {
println("forEach: $it")}}Copy the code
Results:
filter: 1
filter: 2
map: 2
forEach: 5
filter: 3
filter: 4
map: 4
forEach: 9
Copy the code
fun main(a) {
val list = listOf(1.2.3.4)
// region sequence
list.filter {
println("filter: $it")
it % 2= =0
}.map {
println("map: $it")
it * 2 + 1
}.forEach {
println("forEach: $it")}}Copy the code
Results:
filter: 1
filter: 2
filter: 3
filter: 4
map: 2
map: 4
forEach: 5
forEach: 9
Copy the code
AsSequence () converts the list sequence into a lazy sequence, that is, it obtains one data in the list, processes the whole process, and then obtains the next data in the list for process processing. If there is no asSequence(), all data in the list will be processed by filter and then map. Finally, forEeach processes
(6) flatMap operation
All the elements are mapped to the new set one by one, and then all the new sets are merged to get one setJava:
list.stream().flatMap(e -> {
ArrayList<Integer> integers = new ArrayList<>(e);
for (int i = 0; i < e; i++) {
integers.add(i);
}
return integers.stream();
});
/ / [1, 2, 3] - > [0,0,1,0,1,2]
Copy the code
Kotlin:
list.flatMap {
0 until it
}
.joinToString().let(::println)
list.asSequence()
.flatMap {
(0 until it).asSequence()
}
.joinToString().let(::println)
Copy the code
(7) Aggregation operation of collection
A fold: Kotlin:
list.fold(StringBuilder()) { acc, i ->
acc.append(i)
}
Copy the code
Acc is the result of the last concatenation, and I is the element traversed by the list
(7) Zip transformation
(5) SAM conversion
(1) Java SAM
Java’s anonymous inner classes:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(new Runnable() {
@Override
public void run(a) {
System.out.println("run in executor."); }});Copy the code
Java SAM:
executor.submit(() -> System.out.println("run in executor."));
Copy the code
(2) SAM of Kotlin
Kotlin’s anonymous inner class:
executor.submit(object : Runnable {
override fun run(a) {
println("run in executor.")}})Copy the code
Short for anonymous inner class:
executor.submit(Runnable {
println("run in executor.")})Copy the code
Kotlin SAM:
executor.submit { println("run in executor.")}Copy the code
(3) SAM conversion supports comparison
(4) Small case of SAM
Java:
public class EventManager {
interface OnEventListener {
void onEvent(int event);
}
private HashSet<OnEventListener> onEventListeners = new HashSet<>();
public void addOnEventListener(OnEventListener onEventListener) {
this.onEventListeners.add(onEventListener);
}
public void removeOnEventListener(OnEventListener onEventListener) {
this.onEventListeners.remove(onEventListener); }}Copy the code
Kotlin:
fun main(a) {
val eventManager = EventManager()
val onEvent = object : EventManager.OnEventListener {
override fun onEvent(event: Int) {
println("onEvent $event")}}val onEvent2 = EventManager.OnEventListener{
println("onEvent $it")
}
eventManager.addOnEventListener(onEvent)
eventManager.removeOnEventListener(onEvent)
}
Copy the code
(6) Case: Count the number of characters
fun main(a) {
File("build.gradle").readText() // 1. read file
.toCharArray() // 2. String is converted to an array of characters.filter { ! it.isWhitespace() }// 3. Filter white space
The isWhitespace() method is used to check whether specified characters are whitespace characters, including Spaces, TAB keys, and newlines
.groupBy { it } // Get the result (if no number is counted) : {p=[p, p, p, p, p, p, p, p, p, p, p, p, p], l=[l, l, l, l, l, l, l, l, l, l, l, l, l, l, l, l, l, l]
.map {
it.key to it.value.size
}.let {
println(it)
}
}
Copy the code
Results:
[(p, 13), (l, 18), (u, 10), (g, 12), (i, 36), (n, 36), (s, 18), ({, 6), (d, 6), (', 16), (j, 9), (a, 16), (v, 9), (o, 33), (r, 21), (., 14), (e, 35), (t, 28), (b, 5), (k, 7), (m, 14), (1, 7), (3, 1), (6, 1), (0, 2), (}, 6), (c, 7), (y, 2), (h, 1), (-, 5), (S, 3), (N, 2), (A, 2), (P, 1), (H, 1), (O, 3), (T, 4), (C, 5), (=, 4), ((, 1), (), 1), (", 10), (:, 6), (8, 3), (,, 3), (4, 1), (2, 1), (K, 3), (f, 2), ([, 1), (X, 4), (L, 2), (+, 2), (w, 1), (I, 1), (F, 2), (], 1)]
Copy the code
(7) Case: HTML DSL
Code:
interface Node {
fun render(a): String
}
class StringNode(val content: String) : Node {
override fun render(a): String {
return content
}
}
class BlockNode(val name: String) : Node {
val children = ArrayList<Node>()
val properties = HashMap<String, Any>()
override fun render(a): String {
return "" ""$name ${properties.map { "${it.key}= '${it.value}'" }
.joinToString(" ")}>${children.joinToString("") { it.render() }} < /$name> "" "
}
operator fun String.invoke(block: BlockNode. () - >Unit): BlockNode {
val node = BlockNode(this)
node.block()
this@BlockNode.children += node
return node
}
operator fun String.invoke(value: Any) {
this@BlockNode.properties[this] = value
}
operator fun String.unaryPlus(a) {
this@BlockNode.children += StringNode(this)}}fun html(block: BlockNode. () - >Unit): BlockNode {
val html = BlockNode("html")
html.block()
return html
}
fun BlockNode.head(block: BlockNode. () - >Unit): BlockNode {
val head = BlockNode("head")
head.block()
this.children += head
return head
}
fun BlockNode.body(block: BlockNode. () - >Unit): BlockNode {
val head = BlockNode("body")
head.block()
this.children += head
return head
}
fun main(a) {
val htmlContent = html {
head {
"meta" { "charset"("UTF-8") }
}
body {
"div" {
"style"(
""" width: 200px; height: 200px; line-height: 200px; background-color: #C9394A; text-align: center """.trimIndent()
)
"span" {
"style"(
""" color: white; font-family: Microsoft YaHei """.trimIndent()
)
+"Hello HTML DSL!!"
}
}
}
}.render()
File("Kotlin.html").writeText(htmlContent)
}
Copy the code
Get the kotlin.html file:
<html ><head ><meta charset='UTF-8'></meta></head><body ><div style='width: 200px;
height: 200px;
line-height: 200px;
background-color: #C9394A;
text-align: center'><span style='color: white;
font-family: Microsoft YaHei'>Hello HTML DSL!! </span></div></body></html>Copy the code
Use Google Chrome to open the kotlin.html file
Practice: Experience Gradle Kotlin DSL
Convert a Groovy DSL Gradle to a Kotlin DSL Gradle
(1) Name change
Gradle changed to settings.gradle. KTS build.gradle changed to build.gradle. KTS
(2) Modify the content
settings.gradle
rootProject.name = 'HelloWorld'
Copy the code
Settings.gradle.kts (Modify content)
rootProject.name = "HelloWorld"
Copy the code
build.gradle
plugins {
id 'java'
id 'org.jetbrains.kotlin.jvm' version '1.3.60'
}
group 'com.lzacking.kotlin'
version 1.0 the SNAPSHOT ' '
sourceCompatibility = 1.8
repositories {
maven {
url "https://maven.aliyun.com/repository/central"
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "Com. Google. Code. Gson: gson: 2.8.1"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
Copy the code
Build.gradle.kts (modified)
import org.lzacking.kotlin.gradle.tasks.KotlinCompile
plugins {
java
//id ("java")
kotlin("jvm") version ("1.3.60")
/ / id (" org. Jetbrains. Kotlin. The JVM ") version (" 1.3.60 ")
}
group = "com.bennyhuo.kotlin"
version = "1.0 the SNAPSHOT"
java {
sourceCompatibility = JavaVersion.VERSION_1_8
}
repositories {
maven("https://maven.aliyun.com/repository/central")
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("Com. Google. Code. Gson: gson: 2.8.1")
testCompile(group = "junit", name = "junit", version = "4.12")
}
val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions {
jvmTarget = "1.8"
}
val compileTestKotlin: KotlinCompile by tasks
compileTestKotlin.kotlinOptions {
jvmTarget = "1.8"
}
Copy the code