├── gradle.properties
├── src
├── main
│ ├── resources
│ │ └── Hello.txt
│ ├── kotlin
│ │ ├── coroutine
│ │ │ ├── blogpost
│ │ │ │ ├── structuredconcurrency
│ │ │ │ │ ├── hello.txt
│ │ │ │ │ ├── job
│ │ │ │ │ │ ├── CancelJobFiboSuspendDemo.kt
│ │ │ │ │ │ ├── NestedCallJobDemo.kt
│ │ │ │ │ │ ├── SimpleJobDemo.kt
│ │ │ │ │ │ ├── ParentChildByJobDemo.kt
│ │ │ │ │ │ ├── NestedCallCancelDemo.kt
│ │ │ │ │ │ ├── CancelJobDemo.kt
│ │ │ │ │ │ ├── CancelJobFiboDemo.kt
│ │ │ │ │ │ └── ParentChildByContextDemo.kt
│ │ │ │ │ ├── FileClosedDemoFixed.kt
│ │ │ │ │ ├── BrokenAbstractionDemo.kt
│ │ │ │ │ ├── SayHelloWorldInContext.kt
│ │ │ │ │ ├── UseContextDemo.kt
│ │ │ │ │ ├── SayHelloWorldInJob.kt
│ │ │ │ │ ├── FileClosedDemo.kt
│ │ │ │ │ ├── JobDemo.kt
│ │ │ │ │ └── StructuredJobDemo.kt
│ │ │ │ ├── CancelJobDemo.kt
│ │ │ │ ├── ContextIsLikeSet.kt
│ │ │ │ ├── AsyncApiCatchDemo.kt
│ │ │ │ ├── GlobalScopeCallstack.kt
│ │ │ │ ├── SuspendContextDemo.kt
│ │ │ │ ├── ContextElementDemo.kt
│ │ │ │ ├── GoStyleCancelDemo.kt
│ │ │ │ ├── ContextDemo.kt
│ │ │ │ ├── CaptureContextDemo.kt
│ │ │ │ └── ArrowDemo.kt
│ │ │ ├── MyInterfaceJava.java
│ │ │ ├── Test2.java
│ │ │ ├── Log.kt
│ │ │ ├── CoroutineAndCallback.kt
│ │ │ ├── continuation
│ │ │ │ ├── SuspendContinuationDemo.kt
│ │ │ │ ├── CallDelayManuallyDemo.kt
│ │ │ │ └── ManualContinuationExercise.kt
│ │ │ ├── flow
│ │ │ │ ├── toy
│ │ │ │ │ ├── WrongContextDemo.kt
│ │ │ │ │ ├── FlowImplDemo.kt
│ │ │ │ │ └── FlowImplDemoWithoutReceiver.kt
│ │ │ │ ├── ContextPreservationDemo.kt
│ │ │ │ ├── FlatmapDemo.kt
│ │ │ │ ├── SearchPrototype.kt
│ │ │ │ ├── ExceptionHandlingDemo.kt
│ │ │ │ ├── NoBackpressure.kt
│ │ │ │ ├── SharedFlowMutableList.kt
│ │ │ │ ├── CancelFlowByException.kt
│ │ │ │ ├── StateFlowWithCombine.kt
│ │ │ │ ├── StateFlowWithListDemo.kt
│ │ │ │ ├── ConvertToSharedFlow.kt
│ │ │ │ ├── SharedFlowDemo.kt
│ │ │ │ ├── TakeOperatorDemo.kt
│ │ │ │ ├── ChannelToFlow.kt
│ │ │ │ ├── StateFlowWrappedMutableListDemo.kt
│ │ │ │ ├── CancelingFlow.kt
│ │ │ │ ├── LoadMoreRequestDemo.kt
│ │ │ │ ├── InitStateFlow.kt
│ │ │ │ ├── FlowQ3.kt
│ │ │ │ ├── EndlessFlowDemo.kt
│ │ │ │ ├── FlowQuestion.kt
│ │ │ │ ├── FlowOverheadDemo.kt
│ │ │ │ ├── FlowQ4.kt
│ │ │ │ ├── CombineFlow.kt
│ │ │ │ ├── FlowQ2.kt
│ │ │ │ ├── StateFlowCollect.kt
│ │ │ │ ├── FrpState.kt
│ │ │ │ └── FunctionalReactiveUI.kt
│ │ │ ├── CompletableDeferredDemo.kt
│ │ │ ├── caching
│ │ │ │ ├── Mutable.kt
│ │ │ │ ├── StateFlowEnd.kt
│ │ │ │ ├── Immutable.kt
│ │ │ │ ├── StateFlow.kt
│ │ │ │ └── CachingFlowDemo.kt
│ │ │ ├── DeepRecursionDemo.kt
│ │ │ ├── cancellation
│ │ │ │ └── PropogateThroughScope.kt
│ │ │ ├── RetriableCoroutineFactoryDemo.kt
│ │ │ ├── CoroutineContextDemo.kt
│ │ │ ├── SuspendCoroutineDemo.kt
│ │ │ ├── channel
│ │ │ │ ├── ChannelDemo.kt
│ │ │ │ └── SuspendUntilValue.kt
│ │ │ ├── SuspendLamdaDemo.kt
│ │ │ ├── SuspendCoroutineBuilderDemo.kt
│ │ │ ├── FlowDemo.kt
│ │ │ ├── CoroutineScopeDemo.kt
│ │ │ ├── CancelCouroutineByException.kt
│ │ │ ├── ContinuationDemo.kt
│ │ │ ├── LazyCoroutine.kt
│ │ │ ├── Cancel.kt
│ │ │ ├── ErrorPropogation.kt
│ │ │ ├── AsyncCrash.kt
│ │ │ ├── RaceDeferredDemo.kt
│ │ │ ├── actor
│ │ │ │ ├── ActorOverheadDemo.kt
│ │ │ │ └── DataStoreDemo.kt
│ │ │ ├── ExceptionDemo.kt
│ │ │ ├── ContinuationInterceptorDemo.kt
│ │ │ ├── SuspendingLambdaDemo.kt
│ │ │ └── RetriableCoroutine.kt
│ │ ├── types
│ │ │ ├── UnitDemo.kt
│ │ │ ├── Unsigned.ws.kts
│ │ │ ├── MutipleInterface.kt
│ │ │ ├── CompanionAsync.kt
│ │ │ └── DelegationDemo.kt
│ │ ├── string
│ │ │ ├── ParseUrl.ws.kts
│ │ │ ├── StringDemo.kt
│ │ │ └── Quadratic.kt
│ │ ├── stdlib
│ │ │ ├── Require.kt
│ │ │ ├── Sublist.kt
│ │ │ └── Set.ws.kts
│ │ ├── oop
│ │ │ ├── Trait.kt
│ │ │ ├── EnumDemo.kt
│ │ │ ├── JavaPrefix.java
│ │ │ └── LeakingThisDemo.kt
│ │ ├── algorithms
│ │ │ ├── sort
│ │ │ │ ├── Swap.kt
│ │ │ │ ├── TestDrive.kt
│ │ │ │ ├── SelectionSort.kt
│ │ │ │ ├── InsertionSort.kt
│ │ │ │ ├── QuickSort.kt
│ │ │ │ ├── QuickSelect2.kt
│ │ │ │ ├── QuickSelect.kt
│ │ │ │ └── quick
│ │ │ │ │ ├── Quickselect.kt
│ │ │ │ │ └── Quicksort.kt
│ │ │ ├── leetcode
│ │ │ │ ├── backtrack
│ │ │ │ │ ├── 78_Subsets.kt
│ │ │ │ │ ├── 46_Permutation.kt
│ │ │ │ │ ├── 22_GenerateParenthesis.kt
│ │ │ │ │ └── 22_GenerateParenthesisDeepRecursive.kt
│ │ │ │ ├── Test.kt
│ │ │ │ ├── 105_ConstructTree.kt
│ │ │ │ ├── 132pattern.kt
│ │ │ │ ├── 3_LongestNonRepeatingSubstring.kt
│ │ │ │ ├── RemoveDuplicateNode.kt
│ │ │ │ ├── Contest.kt
│ │ │ │ ├── calculator
│ │ │ │ │ ├── Expression.kt
│ │ │ │ │ ├── BasicCalculator1.kt
│ │ │ │ │ └── ShuntingYard.kt
│ │ │ │ ├── LRUCache.kt
│ │ │ │ └── GoodPair.kt
│ │ │ ├── MarkovGenerator.kt
│ │ │ └── StackToQueue.kt
│ │ ├── jvm
│ │ │ ├── FinallyDemo.kt
│ │ │ └── ExceptionDemo.kt
│ │ ├── resources
│ │ │ └── ResourceDeclaration.kt
│ │ ├── fp
│ │ │ ├── ArrowExceptionDslDemo.kt
│ │ │ ├── ArrowEitherDemo.kt
│ │ │ ├── ArrowExceptionDemo.kt
│ │ │ ├── SyntaxDepInjectDemo.kt
│ │ │ └── ReaderMonadDemo.kt
│ │ ├── ktor
│ │ │ ├── KtorConnectionDemoClient.kt
│ │ │ ├── KtorConnectionDemo.kt
│ │ │ └── HtmlDemo.kt
│ │ ├── concurrency
│ │ │ ├── IncrementCounterDemo.kt
│ │ │ ├── hashmap.kt
│ │ │ ├── CompletableFututureAnyOfDemo.kt
│ │ │ ├── DeadlockDemo.kt
│ │ │ ├── jcip
│ │ │ │ ├── CatchCancellationExceptionDemo.kt
│ │ │ │ ├── MemoizerJcipDemo.kt
│ │ │ │ ├── MemoizerSuspendableDemo.kt
│ │ │ │ └── AqsValueLatch.kt
│ │ │ └── bank
│ │ │ │ ├── optimistic
│ │ │ │ ├── TransferMoneyTest.kt
│ │ │ │ ├── SimNetworkErrorTest.kt
│ │ │ │ └── BankService.kt
│ │ │ │ └── twopc
│ │ │ │ ├── BankServiceImpl.kt
│ │ │ │ └── BankService.kt
│ │ ├── tips
│ │ │ ├── Singleton.ws.kts
│ │ │ └── List.ws.kts
│ │ ├── io
│ │ │ ├── ReadClassFile.kt
│ │ │ ├── server.kt
│ │ │ ├── ConcurrentFileWriterDemo.kt
│ │ │ ├── client.kt
│ │ │ └── retrofit.kt
│ │ ├── cli
│ │ │ ├── CliDemo.kt
│ │ │ └── ObjectOrientedStyle.kt
│ │ ├── dataloader
│ │ │ ├── JavaDataLoader.kt
│ │ │ └── DataloaderDemo.kt
│ │ ├── rx
│ │ │ ├── ParallelComposition.kt
│ │ │ ├── RxApiDemo.kt
│ │ │ ├── RxDemo.kt
│ │ │ └── ComparisonWithSequenceDemo.kt
│ │ ├── serialization
│ │ │ ├── SerializableDemo.kt
│ │ │ ├── SerializationDemo.kt
│ │ │ └── MoshiDemo.kt
│ │ ├── kmongo.kt
│ │ ├── excercise
│ │ │ └── LazyListImpl.kt
│ │ ├── ktorm
│ │ │ ├── KtormPgDemo.kt
│ │ │ └── KtormDemo.kt
│ │ ├── rutang
│ │ │ └── WeeklyActiveData.kt
│ │ ├── compose
│ │ │ └── ComposeToy.kt
│ │ └── TransferMoneyDemo.kt
│ └── java
│ │ ├── HandlerDemo.java
│ │ ├── Gender.java
│ │ ├── StringDemo.java
│ │ └── StaticDemo.java
└── test
│ └── kotlin
│ ├── ResourceTest.kt
│ ├── StateFlowTest.kt
│ ├── HookTest.kt
│ ├── DynamicTest.kt
│ └── CustomConsumerTest.kt
├── .gitignore
├── settings.gradle.kts
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .idea
├── codeStyles
│ ├── codeStyleConfig.xml
│ └── Project.xml
├── modules
│ └── kotlin-playground.main.iml
├── compiler.xml
├── vcs.xml
├── .gitignore
├── modules.xml
├── misc.xml
├── gradle.xml
└── jarRepositories.xml
├── out.txt
└── gradlew.bat
/gradle.properties:
--------------------------------------------------------------------------------
1 | kotlin.code.style=official
--------------------------------------------------------------------------------
/src/main/resources/Hello.txt:
--------------------------------------------------------------------------------
1 | Hello World!
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Project exclude paths
2 | /.gradle/
3 | /build/
--------------------------------------------------------------------------------
/src/test/kotlin/ResourceTest.kt:
--------------------------------------------------------------------------------
1 |
2 | fun main() {
3 |
4 | }
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "kotlin-playground"
2 |
3 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/hello.txt:
--------------------------------------------------------------------------------
1 | hello world!
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/CancelJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 |
--------------------------------------------------------------------------------
/src/main/java/HandlerDemo.java:
--------------------------------------------------------------------------------
1 | public class HandlerDemo {
2 | // a = Void.TYPE;
3 | }
4 |
--------------------------------------------------------------------------------
/src/main/kotlin/types/UnitDemo.kt:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | object A
4 |
5 | fun main() {
6 | println(Unit)
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/string/ParseUrl.ws.kts:
--------------------------------------------------------------------------------
1 | import java.net.URI
2 |
3 |
4 | val destination = URI("/subject?id=1")
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yujinyan/kotlin-playground/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/src/main/kotlin/stdlib/Require.kt:
--------------------------------------------------------------------------------
1 | package stdlib
2 |
3 | fun main() {
4 | val a: String? = null
5 | requireNotNull(a)
6 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/MyInterfaceJava.java:
--------------------------------------------------------------------------------
1 | package coroutine;
2 |
3 | public interface MyInterfaceJava {
4 | void hi();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/oop/Trait.kt:
--------------------------------------------------------------------------------
1 | package oop
2 |
3 | class Repository
4 |
5 | interface HasRepository {
6 | val repository: Repository
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/types/Unsigned.ws.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE")
2 |
3 | val v: Short = -12345
4 | println(v.toUShort())
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/Test2.java:
--------------------------------------------------------------------------------
1 | package coroutine;
2 |
3 | public class Test2 {
4 | Integer getP() {
5 | return 1;
6 |
7 | }
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/src/main/kotlin/types/MutipleInterface.kt:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | interface I1 {
4 | fun foo(): Int
5 | }
6 |
7 | interface I2 {
8 | fun foo(): String
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/Gender.java:
--------------------------------------------------------------------------------
1 | public enum Gender {
2 | Male, Female;
3 |
4 | public static void main(String[] args) {
5 | var name = Gender.Male.name();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/Swap.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | fun IntArray.swap(i: Int, j: Int) {
4 | val temp = this[j]
5 | this[j] = this[i]
6 | this[i] = temp
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/Log.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | //fun log(msg: String) = println("[${Thread.currentThread().name}] $msg")
4 |
5 | fun log(msg: String) = println("$msg")
6 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/modules/kotlin-playground.main.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/out.txt:
--------------------------------------------------------------------------------
1 | 33333333333333333333444444444444444444447777777777777777777788888888888888888888000000000000000000009999999999999999999922222222222222222222111111111111111111115555555555555555555566666666666666666666
--------------------------------------------------------------------------------
/src/main/kotlin/stdlib/Sublist.kt:
--------------------------------------------------------------------------------
1 | package stdlib
2 |
3 | fun main() {
4 | val oldList = mutableListOf(1, 2, 3)
5 | val subList = oldList.subList(0, 2)
6 | oldList[0] = 100
7 | println(subList)
8 | }
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/oop/EnumDemo.kt:
--------------------------------------------------------------------------------
1 | package oop
2 |
3 | enum class Prefix(val value: String) {
4 | Post("post"), InviteCode("invite-code")
5 | }
6 |
7 | fun main() {
8 | println(Prefix.Post.name)
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/StringDemo.java:
--------------------------------------------------------------------------------
1 | public class StringDemo {
2 | public static void main(String[] args) {
3 | StringBuilder sb = new StringBuilder();
4 | sb.append("hi");
5 | sb.toString();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/ContextIsLikeSet.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.CoroutineName
4 |
5 | fun main() {
6 | println(CoroutineName("foo") + CoroutineName("bar") == CoroutineName("bar"))
7 | }
--------------------------------------------------------------------------------
/src/main/kotlin/oop/JavaPrefix.java:
--------------------------------------------------------------------------------
1 | package oop;
2 |
3 | public enum JavaPrefix {
4 | Post;
5 |
6 | public static void main(String[] args) {
7 | String p = JavaPrefix.Post.name();
8 | }
9 | }
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/kotlin/jvm/FinallyDemo.kt:
--------------------------------------------------------------------------------
1 |
2 | fun test(): Int {
3 | try {
4 | return 1
5 | } finally {
6 | println("hi")
7 | return 2
8 | }
9 | }
10 |
11 | fun main() {
12 | val result = test()
13 | println(result)
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/resources/ResourceDeclaration.kt:
--------------------------------------------------------------------------------
1 | package resources
2 |
3 | val hello = {}.javaClass.getResourceAsStream("/Hello.txt").reader().readText()
4 |
5 | fun printHello() = println(hello)
6 |
7 | fun main() {
8 | println(hello)
9 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/src/main/kotlin/oop/LeakingThisDemo.kt:
--------------------------------------------------------------------------------
1 | package oop
2 |
3 | class Foo {
4 | init {
5 | printBar(this)
6 | }
7 | val bar = "Bar"
8 | }
9 |
10 | fun printBar(foo: Foo) {
11 | println(foo.bar)
12 | }
13 |
14 | fun main() {
15 | Foo()
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/fp/ArrowExceptionDslDemo.kt:
--------------------------------------------------------------------------------
1 | package fp
2 |
3 | import arrow.core.Either
4 | import arrow.core.computations.either
5 | import arrow.core.left
6 | import arrow.core.right
7 | import kotlin.random.Random
8 |
9 |
10 | fun main() {
11 |
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /../../../../../../../:\Users\yujinyan\code\study\kotlin-playground\.idea/dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/CoroutineAndCallback.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | fun getToken(block: (String) -> Unit) {
4 |
5 | }
6 |
7 | fun upload(token: String) {
8 | // upload...
9 | }
10 |
11 |
12 | fun main() {
13 | getToken { token ->
14 | upload(token)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/jvm/ExceptionDemo.kt:
--------------------------------------------------------------------------------
1 | package jvm
2 |
3 | import java.lang.IllegalArgumentException
4 |
5 | fun foo(): IllegalArgumentException {
6 | return bar()
7 | }
8 |
9 | fun bar() = IllegalArgumentException()
10 |
11 | fun main() {
12 | val e = foo()
13 | e.printStackTrace()
14 | }
--------------------------------------------------------------------------------
/src/main/kotlin/string/StringDemo.kt:
--------------------------------------------------------------------------------
1 |
2 | fun textLength(value: String) = value.codePoints().toArray().fold(0) { acc, c ->
3 | if (c > 256) acc + 2
4 | else (acc + 1)
5 | }
6 |
7 | fun main() {
8 | // println(textLength("你好"))
9 | // println(textLength("hello"))
10 | textLength("🎈🎆🎇a你好")
11 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/continuation/SuspendContinuationDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.continuation
2 |
3 | import kotlinx.coroutines.delay
4 |
5 | //suspend fun foo() = bar()
6 |
7 | suspend fun bar(): String {
8 | delay(100)
9 | return "bar"
10 | }
11 |
12 | suspend fun main() {
13 | val b = bar()
14 | println(b)
15 | }
--------------------------------------------------------------------------------
/src/main/kotlin/ktor/KtorConnectionDemoClient.kt:
--------------------------------------------------------------------------------
1 | package ktor
2 |
3 | import io.ktor.client.*
4 | import io.ktor.client.engine.cio.*
5 | import io.ktor.client.request.*
6 |
7 |
8 | suspend fun main() {
9 | HttpClient(CIO).use {
10 | val result = it.get("http://localhost:8080/")
11 | println(result)
12 | }
13 | }
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/IncrementCounterDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.launch
5 |
6 | suspend fun main() {
7 | var counter = 0
8 | coroutineScope {
9 | repeat(10_000) {
10 | launch { counter++ }
11 | }
12 | }
13 | println("counter: $counter")
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/kotlin/tips/Singleton.ws.kts:
--------------------------------------------------------------------------------
1 | @file:Suppress("HasPlatformType", "unused")
2 |
3 | import java.math.BigInteger
4 | import java.util.*
5 |
6 | fun initObject() = BigInteger
7 | .probablePrime(128, Random())
8 |
9 | // singleton, eager
10 | val obj1 = initObject()
11 |
12 | // singleton, lazy, thread-safe
13 | val obj2 by lazy { initObject() }
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/TestDrive.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 |
4 | private val IntArray.isSorted: Boolean
5 | get() {
6 | for (i in 1..lastIndex) {
7 | if (get(i) <= get(i - 1)) return false
8 | }
9 | return true
10 | }
11 |
12 | fun main() {
13 | (1..1000).shuffled().toIntArray()
14 | .let {
15 | insertionSort(it)
16 | require(it.isSorted) { "not sorted" }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/SelectionSort.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | fun selectionSort(arr: IntArray) {
4 | for (i in 0..arr.lastIndex) {
5 | var min = i
6 | for (j in i + 1..arr.lastIndex) {
7 | if (arr[j] < arr[min]) min = j
8 | }
9 | arr.swap(i, min)
10 | }
11 | }
12 |
13 | fun main() {
14 | val array = intArrayOf(3, 1, 5, 2)
15 | selectionSort(array)
16 | println(array.asList())
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/toy/WrongContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow.toy
2 |
3 | import kotlinx.coroutines.Dispatchers
4 | import kotlinx.coroutines.flow.collect
5 | import kotlinx.coroutines.withContext
6 | import kotlin.coroutines.coroutineContext
7 |
8 | suspend fun main() {
9 | FlowImpl {
10 | withContext(Dispatchers.IO) {
11 | emit(1)
12 | }
13 | }.collect {
14 | println(coroutineContext)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/CompletableDeferredDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 |
5 | suspend fun main() {
6 |
7 | coroutineScope {
8 | val c = CompletableDeferred(coroutineContext[Job])
9 | launch {
10 | delay(1000)
11 | c.complete(1)
12 | }
13 |
14 | launch {
15 | val result = c.await()
16 | println("got $result")
17 | println("got ${c.await()}")
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/ReadClassFile.kt:
--------------------------------------------------------------------------------
1 | package io
2 |
3 | import java.io.File
4 |
5 |
6 | fun main() {
7 | val file = File("C:\\Users\\yujinyan\\code\\study\\java\\Adder.class")
8 | .readBytes()
9 |
10 | val seq = file.iterator().asSequence()
11 | // seq.
12 | // seq.take(4).toList().also { println(it) }
13 | seq.take(2).toList().also { println(it) }
14 |
15 | // file.take(4).also { println(it) }
16 | // file.take(2).also { println(it) }
17 | }
--------------------------------------------------------------------------------
/src/main/java/StaticDemo.java:
--------------------------------------------------------------------------------
1 | @SuppressWarnings("ALL")
2 | public class StaticDemo {
3 | static class Foo {
4 | static int foo = loadFoo();
5 |
6 | static int loadFoo() {
7 | throw new IllegalStateException();
8 | }
9 |
10 | static class Bar {
11 | static int bar = 1;
12 | }
13 | }
14 |
15 | public static void main(String[] args) {
16 | System.out.println(Foo.foo);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/CancelJobFiboSuspendDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import kotlinx.coroutines.*
4 |
5 | suspend fun main() {
6 | val job = GlobalScope.launch {
7 | printFibonacciSlowly(50)
8 | }
9 | delay(100)
10 | job.cancelAndJoin()
11 | }
12 |
13 | suspend fun printFibonacciSlowly(n: Int) {
14 | for (i in 0..n) {
15 | yield()
16 | println(fibonacci(i))
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/ContextPreservationDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.Dispatchers
4 | import kotlinx.coroutines.flow.collect
5 | import kotlinx.coroutines.flow.flow
6 | import kotlinx.coroutines.withContext
7 |
8 | suspend fun main() {
9 | val f = flow { // BAD!!
10 | emit(1)
11 | val value = withContext(Dispatchers.IO) { 2 }
12 | emit(value)
13 | }
14 |
15 | f.collect {
16 | println(it)
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/InsertionSort.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | import algorithms.sort.quick.swap
4 |
5 | // eg. 3,5,1,2,4
6 | fun insertionSort(arr: IntArray) {
7 | for (i in 1..arr.lastIndex) {
8 | for (j in i downTo 1) {
9 | if (arr[j] < arr[j - 1]) {
10 | swap(arr, j, j - 1)
11 | } else break
12 | }
13 | }
14 | }
15 |
16 | fun main() {
17 | val array = intArrayOf(3, 1, 5, 2)
18 | insertionSort(array)
19 | println(array.asList())
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/types/CompanionAsync.kt:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | import kotlinx.coroutines.CoroutineScope
4 | import kotlinx.coroutines.GlobalScope
5 | import kotlinx.coroutines.async
6 | import types.SomeDialog.Companion.newInstanceAsync
7 |
8 | class SomeDialog {
9 | companion object {
10 | fun CoroutineScope.newInstanceAsync() = async {
11 | SomeDialog()
12 | }
13 | }
14 | }
15 |
16 | suspend fun main() {
17 | val result = GlobalScope.newInstanceAsync()
18 | result.await()
19 | }
--------------------------------------------------------------------------------
/src/test/kotlin/StateFlowTest.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.ExperimentalCoroutinesApi
2 | import kotlinx.coroutines.flow.MutableStateFlow
3 | import kotlinx.coroutines.flow.collect
4 | import kotlinx.coroutines.flow.map
5 |
6 | @ExperimentalCoroutinesApi
7 | suspend fun main() {
8 | val counter = MutableStateFlow(0)
9 | val doubledCounter = counter.map { it * 2 }
10 | counter.value++
11 | counter.value++
12 | doubledCounter.collect {
13 | println(it)
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/FileClosedDemoFixed.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.*
4 | import java.io.InputStream
5 |
6 |
7 | fun CoroutineScope.process(stream: InputStream) {
8 | launch {
9 | delay(1000)
10 | stream.reader().readText()
11 | }
12 | }
13 |
14 | suspend fun main() {
15 | {}.javaClass.getResourceAsStream("/Hello.txt").use {
16 | coroutineScope {
17 | process(it)
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/AsyncApiCatchDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlin.concurrent.thread
4 |
5 | object AsyncApiCatchDemo {
6 | fun foo() {
7 | thread {
8 | error("whoops")
9 | }
10 | // Thread {
11 | // println("thread is ${Thread.currentThread().name}")
12 | // error("whoops")
13 | // }.start()
14 | }
15 | }
16 |
17 | fun main() {
18 | try {
19 | AsyncApiCatchDemo.foo()
20 | } catch (e: Throwable) {
21 | println(e)
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/stdlib/Set.ws.kts:
--------------------------------------------------------------------------------
1 | package stdlib
2 |
3 | data class Carrot(val id: Int, val name: String)
4 |
5 | val carrots1: Map = listOf(
6 | Carrot(1, "1"),
7 | Carrot(2, "1"),
8 | ).associateBy { it.id }
9 |
10 | val carrots2: Map = listOf(
11 | Carrot(3, "1"),
12 | Carrot(4, "1"),
13 | ).associateBy { it.id }
14 |
15 | carrots1 + carrots2
16 | carrots1 - carrots2
17 | carrots1.values intersect carrots2.values
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/io/server.kt:
--------------------------------------------------------------------------------
1 | package io
2 |
3 | import io.ktor.application.*
4 | import io.ktor.response.*
5 | import io.ktor.routing.*
6 | import io.ktor.server.engine.*
7 | import io.ktor.server.netty.*
8 | import kotlinx.coroutines.delay
9 |
10 | fun main() {
11 | val server = embeddedServer(Netty, port = 8080) {
12 | routing {
13 | get("/test") {
14 | delay(1000)
15 | call.respondText("hi, ${call.request.queryParameters["id"]}")
16 | }
17 | }
18 | }
19 | server.start(wait = true)
20 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/hashmap.kt:
--------------------------------------------------------------------------------
1 | package concurrency
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlin.concurrent.thread
5 |
6 | suspend fun main() {
7 | val map = HashMap()
8 |
9 | // coroutineScope {
10 | // repeat(10000) { i -> map[i.toString()] = 1.toString() }
11 | // }
12 |
13 | repeat(100) { i ->
14 | thread {
15 | map[i.toString()] = 1.toString()
16 | }
17 | }
18 |
19 | Thread.sleep(6000)
20 |
21 | // println(map.size)
22 | map.forEach { t, u -> println(t) }
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/caching/Mutable.kt:
--------------------------------------------------------------------------------
1 | package coroutine.caching
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.launch
8 |
9 | suspend fun main() {
10 | val state = MutableStateFlow(mutableListOf())
11 |
12 | GlobalScope.launch {
13 | delay(100)
14 | state.value = state.value.apply { add(1) }
15 | }
16 | state.collect {
17 | println(it) // []
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/BrokenAbstractionDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.Dispatchers
4 | import kotlinx.coroutines.GlobalScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.launch
7 |
8 |
9 |
10 |
11 | fun main() {
12 | writeData()
13 | // 🤔 数据写完了吗?可以读这个数据了吗?
14 | }
15 |
16 | fun writeData() {
17 | GlobalScope.launch(Dispatchers.IO) {
18 | // doing some work ..
19 | delay(1000)
20 | // write data
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/DeepRecursionDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | class Tree(val left: Tree?, val right: Tree?)
4 |
5 | @ExperimentalStdlibApi
6 | val depth = DeepRecursiveFunction { tree: Tree? ->
7 | if (tree == null) 0 else maxOf(
8 | callRecursive(tree.left),
9 | callRecursive(tree.right),
10 | ) + 1
11 | }
12 |
13 | @ExperimentalStdlibApi
14 | fun main() {
15 | val treeGenerator = generateSequence(Tree(null, null)) { prev -> Tree(prev, null) }
16 | val deepTree = treeGenerator.take(100_000).last()
17 | println(depth(deepTree))
18 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/NestedCallJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.isActive
6 | import kotlinx.coroutines.launch
7 | import kotlin.coroutines.coroutineContext
8 |
9 | suspend fun main() =
10 | GlobalScope.launch {
11 | foo()
12 | }.join()
13 |
14 | suspend fun foo() =
15 | bar()
16 |
17 | suspend fun bar() {
18 | println(coroutineContext.isActive)
19 | delay(1000)
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/SimpleJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import coroutine.blogpost.structuredconcurrency.printAsTree
4 | import io.ktor.util.*
5 | import kotlinx.coroutines.*
6 | import kotlin.time.ExperimentalTime
7 |
8 | @ExperimentalTime
9 | @InternalAPI
10 | suspend fun main() = coroutineScope {
11 | val job = Job()
12 |
13 | launch(job) {
14 | delay(1000)
15 | println("foo")
16 | }
17 | launch(job) {
18 | delay(1500)
19 | println("bar")
20 | }
21 |
22 | Unit
23 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/GlobalScopeCallstack.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.launch
5 |
6 | object GlobalScopeCallstack {
7 | suspend fun foo() {
8 | println("called foo")
9 | bar()
10 | }
11 |
12 | suspend fun bar() {
13 | println("called bar")
14 | GlobalScope.launch {
15 | baz()
16 | }
17 | }
18 |
19 | suspend fun baz() {
20 | error("whoops")
21 | }
22 | }
23 |
24 | suspend fun main() {
25 | GlobalScopeCallstack.foo()
26 | while (true) {
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/SayHelloWorldInContext.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 |
6 | suspend fun sayHelloWorldInContext() {
7 | GlobalScope.launch(coroutineContext) {
8 | delay(500)
9 | print("Hello ")
10 | }
11 | GlobalScope.launch(coroutineContext) {
12 | delay(1000)
13 | print("World!")
14 | }
15 | }
16 |
17 | fun main() = runBlocking {
18 | launch {
19 | sayHelloWorldInContext()
20 | }.cancelAndJoin()
21 | }
22 |
23 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/cancellation/PropogateThroughScope.kt:
--------------------------------------------------------------------------------
1 | package coroutine.cancellation
2 |
3 | import kotlinx.coroutines.CancellationException
4 | import kotlinx.coroutines.supervisorScope
5 |
6 | suspend fun main() {
7 | // coroutineScope {
8 | // launch {
9 | // throw IllegalStateException("1")
10 | //// throw CancellationException("1")
11 | // }
12 | // }
13 | //
14 | // coroutineScope {
15 | // throw CancellationException("2")
16 | // }
17 |
18 | supervisorScope {
19 | throw CancellationException()
20 | }
21 |
22 | println("end")
23 |
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlatmapDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.ExperimentalCoroutinesApi
5 | import kotlinx.coroutines.flow.collect
6 | import kotlinx.coroutines.flow.flatMapLatest
7 | import kotlinx.coroutines.flow.flow
8 | import kotlinx.coroutines.flow.flowOf
9 |
10 | @ExperimentalCoroutinesApi
11 | suspend fun main() {
12 | val f = flowOf(1, 2, 3).flatMapLatest {
13 | flow {
14 | emit(it * it)
15 | emit(it * it * it)
16 | }
17 | }
18 |
19 | f.collect {
20 | log("collected $it")
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/RetriableCoroutineFactoryDemo.kt:
--------------------------------------------------------------------------------
1 | import coroutine.log
2 | import kotlinx.coroutines.channels.Channel
3 | import java.util.concurrent.atomic.AtomicInteger
4 |
5 | fun attemptFactory() = { block: suspend () -> T ->
6 | val retryRequest = Channel()
7 | val failedCount = AtomicInteger(0)
8 | suspend {
9 | while (true) {
10 | try {
11 | block()
12 | } catch (e: Throwable) {
13 | log("caught exception $e")
14 | failedCount.incrementAndGet()
15 | retryRequest.receive()
16 | }
17 | }
18 | }
19 | }
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/main/kotlin/cli/CliDemo.kt:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import kotlinx.cli.ArgParser
4 | import kotlinx.cli.ArgType
5 | import kotlinx.cli.default
6 |
7 | fun useParser(block: ArgParser.() -> Unit) {
8 | val parser = ArgParser("")
9 | parser.block()
10 | }
11 |
12 |
13 | fun main(args: Array) = useParser {
14 | val output by option(ArgType.String).default("output.csv")
15 | val shouldSend by option(ArgType.Boolean).default(false)
16 |
17 | parse(args)
18 |
19 | println("writing to file $output")
20 |
21 | if (shouldSend) {
22 | println("sending file $shouldSend")
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/dataloader/JavaDataLoader.kt:
--------------------------------------------------------------------------------
1 | package dataloader
2 |
3 | import org.dataloader.BatchLoader
4 | import org.dataloader.DataLoader
5 | import java.util.concurrent.CompletableFuture
6 |
7 |
8 | fun main() {
9 | val batchLoader = BatchLoader {
10 | CompletableFuture.supplyAsync {
11 | listOf(User(1, 3), User(2, 4))
12 | }
13 | }
14 |
15 | val userLoader = DataLoader.newDataLoader(batchLoader)
16 |
17 | val user1 = userLoader.load(1).thenAccept { println(it) }
18 | val user2 = userLoader.load(2).thenAccept { println(it) }
19 |
20 | userLoader.dispatchAndJoin()
21 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/SuspendContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.CoroutineContext
5 | import kotlin.coroutines.coroutineContext
6 |
7 | suspend fun main() {
8 |
9 | suspend fun foo(context: CoroutineContext) {
10 | println(coroutineContext)
11 | println(context)
12 | Dispatchers.Default
13 | // withContext()
14 | // println(coroutineContext == context)
15 | }
16 |
17 | coroutineScope {
18 | val context = Dispatchers.IO
19 | launch(context) {
20 | foo(context)
21 | }
22 | }
23 |
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | IDE
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/main/kotlin/types/DelegationDemo.kt:
--------------------------------------------------------------------------------
1 | package types
2 |
3 | interface OnClickHandler {
4 | fun onClick()
5 | }
6 |
7 | class Handler(val r: Any): OnClickHandler {
8 | init {
9 | println((r as AnotherActivity).someField)
10 | }
11 | override fun onClick() {
12 | }
13 | }
14 |
15 |
16 |
17 |
18 | class SomeActivity: OnClickHandler by Handler(1) {
19 |
20 | }
21 |
22 | class AnotherActivity: OnClickHandler {
23 | val handler = Handler(this)
24 | val someField = Any()
25 | override fun onClick() {
26 | TODO("Not yet implemented")
27 | }
28 | }
29 |
30 | fun main() {
31 | AnotherActivity()
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/ParentChildByJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 |
6 | suspend fun sayHelloWorld(): String {
7 | val job = Job()
8 | val task1 = GlobalScope.async(job) {
9 | delay(500)
10 | "Hello "
11 | }
12 | val task2 = GlobalScope.async(job) {
13 | delay(1000);
14 | "World!"
15 | }
16 | return task1.await() + task2.await()
17 | }
18 |
19 | fun main() = runBlocking {
20 | launch {
21 | println(sayHelloWorld())
22 | }
23 | println("hi")
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/caching/StateFlowEnd.kt:
--------------------------------------------------------------------------------
1 | package coroutine.caching
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.flow.onCompletion
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 | val state = MutableStateFlow(0)
12 | GlobalScope.launch {
13 | while (true) {
14 | state.value += 1
15 | delay(1000)
16 | }
17 | }
18 |
19 | state
20 | .collect {
21 | println(it)
22 | println(state.replayCache)
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/UseContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 |
6 | suspend fun foo() {
7 | delay(1000)
8 | println("foo")
9 | }
10 |
11 | suspend fun bar() {
12 | delay(800)
13 | error("whoops")
14 | println("bar")
15 | }
16 |
17 | suspend fun composed() {
18 | GlobalScope.launch(coroutineContext) { foo() }
19 | GlobalScope.launch(coroutineContext) { bar() }
20 | }
21 |
22 |
23 | suspend fun main() {
24 | composed()
25 | println("after composed")
26 | while (true) {}
27 | }
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/CoroutineContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.CoroutineContext
5 |
6 | suspend fun foo() {
7 |
8 | }
9 |
10 | suspend fun main() {
11 | val context: CoroutineContext = Dispatchers.IO + CoroutineName("CoCo") + CoroutineName("hi")
12 | val name: CoroutineName? = context[CoroutineName]
13 | println(name)
14 |
15 | (Dispatchers.IO + Printer).also { println(it) }
16 |
17 | // foo()
18 | //
19 | // delay(1000)
20 | //
21 | // println(context)
22 | // coroutineScope {
23 | // launch(context) {
24 | // println(coroutineContext)
25 | // }
26 | // }
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/CompletableFututureAnyOfDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency
2 |
3 | import java.util.concurrent.CompletableFuture
4 | import kotlin.time.ExperimentalTime
5 | import kotlin.time.TimeSource
6 |
7 |
8 | @OptIn(ExperimentalTime::class)
9 | fun main() {
10 | val now = TimeSource.Monotonic.markNow()
11 | val data1 = CompletableFuture.supplyAsync {
12 | Thread.sleep(500);
13 | 1
14 | }
15 |
16 | val data2 = CompletableFuture.supplyAsync {
17 | Thread.sleep(1000)
18 | 2
19 | }
20 |
21 | val result = CompletableFuture.anyOf(data1, data2).get() as Int
22 |
23 | println("got $result, elapsed ${now.elapsedNow()}")
24 | }
--------------------------------------------------------------------------------
/src/main/kotlin/rx/ParallelComposition.kt:
--------------------------------------------------------------------------------
1 | package rx
2 |
3 | import io.reactivex.rxjava3.core.Observable
4 | import io.reactivex.rxjava3.core.Scheduler
5 | import io.reactivex.rxjava3.schedulers.Schedulers
6 |
7 | fun main() {
8 | Observable.range(0, 10)
9 | .flatMap {
10 | Observable.just(it)
11 | .subscribeOn(Schedulers.io())
12 | .map {
13 | println(Thread.currentThread().name)
14 | Thread.sleep(500)
15 | it * it
16 | }
17 | }
18 | .map {
19 | println(Thread.currentThread())
20 | it * it
21 | }
22 | .blockingSubscribe {
23 | println(it)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/caching/Immutable.kt:
--------------------------------------------------------------------------------
1 | package coroutine.caching
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.launch
8 |
9 | suspend fun main() {
10 | val state = MutableStateFlow(listOf())
11 |
12 | GlobalScope.launch {
13 | delay(100)
14 | state.value += 1
15 | state.value += listOf(2, 3)
16 | }
17 |
18 | state.collect {
19 | println(it) // []
20 | // [1]
21 | // [1, 2, 3]
22 |
23 | val a = "Hello"
24 | val b = "$a World"
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/ConcurrentFileWriterDemo.kt:
--------------------------------------------------------------------------------
1 | package io
2 |
3 | import java.io.File
4 | import java.util.concurrent.locks.ReentrantLock
5 | import kotlin.concurrent.thread
6 |
7 | fun main() {
8 | val o = {}
9 | val lock = ReentrantLock()
10 | (0..9).map { i ->
11 | thread {
12 | lock.lock()
13 | File("out.txt").apply {
14 | repeat(20) {
15 | appendText(i.toString())
16 | }
17 | }
18 | lock.unlock()
19 | // File("out.txt").printWriter().use { writer ->
20 | // repeat(20) {
21 | // writer.print(i)
22 | // }
23 | // }
24 | }
25 | }.forEach {
26 | it.join()
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/SearchPrototype.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.flow.MutableSharedFlow
5 | import kotlinx.coroutines.flow.collect
6 | import kotlinx.coroutines.flow.map
7 | import kotlinx.coroutines.launch
8 |
9 | val searchQuery = MutableSharedFlow(1)
10 |
11 | val staticSections = searchQuery.map {
12 | "static sections for $it"
13 | }
14 |
15 | suspend fun main() {
16 | coroutineScope {
17 | launch {
18 | searchQuery.emit("query 1")
19 | }
20 |
21 | launch {
22 | staticSections.collect {
23 | println(it)
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/SayHelloWorldInJob.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 |
6 | suspend fun sayHelloWorld() {
7 | val job = Job(parent = coroutineContext[Job])
8 | GlobalScope.launch(job) {
9 | delay(500)
10 | print("Hello ")
11 | }
12 | GlobalScope.launch(job) {
13 | delay(1000)
14 | print("World!")
15 | }
16 | job.complete()
17 | job.join()
18 | }
19 |
20 | fun main() = runBlocking {
21 | val job = launch {
22 | sayHelloWorld()
23 | }
24 |
25 | delay(100)
26 | job.cancelAndJoin()
27 | delay(2000)
28 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/ExceptionHandlingDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.flow.catch
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.flow.flow
8 | import kotlinx.coroutines.flow.onCompletion
9 |
10 | suspend fun main() {
11 | val flow = flow {
12 | emit(1)
13 | emit(2)
14 | emit(3)
15 | error("whoops")
16 | emit(4)
17 | emit(5)
18 | }
19 | // .catch {
20 | //
21 | // }
22 | .onCompletion {
23 | log("e: $it")
24 | }
25 | .catch {}
26 |
27 | flow.collect {
28 | log("collected $it")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/FileClosedDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.launch
6 | import java.io.File
7 | import java.io.InputStream
8 |
9 | fun process(stream: InputStream) {
10 | GlobalScope.launch {
11 | delay(1000)
12 | stream.reader().readText()
13 | }
14 | }
15 |
16 | fun demo() {
17 | File("./hello.txt").inputStream().use {
18 | process(it)
19 | }
20 | }
21 |
22 | fun main() {
23 | {}.javaClass.getResourceAsStream("/Hello.txt").use {
24 | process(it)
25 | }
26 |
27 | while (true) {
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/SuspendCoroutineDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.runBlocking
4 | import kotlin.coroutines.resume
5 | import kotlin.coroutines.suspendCoroutine
6 |
7 | object SuspendCoroutineDemo {
8 | fun fetchData(block: (Int) -> Unit) {
9 | block(1)
10 | }
11 |
12 | suspend fun fetchData(): Int = suspendCoroutine { cont ->
13 | fetchData {
14 | cont.resume(it)
15 | }
16 | }
17 | }
18 |
19 | fun main() {
20 | // uses callback
21 | SuspendCoroutineDemo.fetchData {
22 | println(it)
23 | }
24 |
25 | // uses suspend function
26 | runBlocking {
27 | val data = SuspendCoroutineDemo.fetchData()
28 | println(data)
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/ktor/KtorConnectionDemo.kt:
--------------------------------------------------------------------------------
1 | package ktor
2 |
3 | import io.ktor.application.*
4 | import io.ktor.response.*
5 | import io.ktor.routing.*
6 | import io.ktor.server.engine.*
7 | import io.ktor.server.netty.*
8 | import kotlinx.coroutines.delay
9 | import kotlinx.coroutines.yield
10 |
11 | fun main() {
12 | embeddedServer(Netty, port = 8080) {
13 | routing {
14 | get("/") {
15 | heavyLifting()
16 | call.respondText("hello world!")
17 | }
18 | }
19 | }.start(wait = true)
20 | }
21 |
22 | suspend fun heavyLifting() {
23 | println("starting to do heavy lifting")
24 | while (true) {
25 | delay(100)
26 | print(".")
27 | yield()
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/backtrack/78_Subsets.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.backtrack
2 |
3 | import algorithms.TracingDeepRecursiveFunction
4 | import algorithms.invoke
5 |
6 |
7 | suspend fun main() {
8 | val result = mutableListOf>()
9 | val arr = listOf(1, 2, 3)
10 |
11 | val list = mutableListOf()
12 |
13 | val subsets = TracingDeepRecursiveFunction f@{ i: Int ->
14 | if (i == arr.size) {
15 | result += list.toList()
16 | return@f
17 | }
18 | list += arr[i]
19 | callRecursive(i + 1)
20 | list.removeAt(list.lastIndex)
21 | callRecursive(i + 1)
22 | }
23 |
24 | subsets(0)
25 | println(result)
26 | }
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/channel/ChannelDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.channel
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.launch
8 |
9 | suspend fun main() {
10 | val channel = Channel(1)
11 |
12 | coroutineScope {
13 | launch {
14 | delay(1000)
15 | channel.send(Unit)
16 | delay(1000)
17 | channel.send(Unit)
18 | }
19 |
20 | delay(3000)
21 |
22 | launch {
23 | for (i in channel) {
24 | println(i)
25 | }
26 | // channel.receive()
27 | // log("received")
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/NoBackpressure.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableStateFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 | val state = MutableStateFlow(0)
12 | coroutineScope {
13 | launch {
14 | while (true) {
15 | delay(1000)
16 | log("updating state")
17 | state.value += 1
18 | }
19 | }
20 |
21 | launch {
22 | state.collect {
23 | log("collecting $it")
24 | delay(20000)
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/SuspendLamdaDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlin.coroutines.Continuation
4 | import kotlin.coroutines.CoroutineContext
5 | import kotlin.coroutines.EmptyCoroutineContext
6 | import kotlin.jvm.functions.Function1
7 |
8 | val s: suspend () -> Int = suspend {
9 | println("in suspend")
10 | 1
11 | }
12 |
13 | fun main() {
14 | println(s::class.java.superclass.name)
15 | s::class.java.interfaces.forEach { println(it) }
16 |
17 | val f = s as Function1, Int>
18 |
19 | f(object : Continuation {
20 | override val context: CoroutineContext = EmptyCoroutineContext
21 | override fun resumeWith(result: Result): Unit = TODO()
22 | })
23 | }
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/SuspendCoroutineBuilderDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import io.ktor.utils.io.*
4 | import kotlin.concurrent.thread
5 | import kotlin.coroutines.resume
6 | import kotlin.coroutines.suspendCoroutine
7 | import kotlin.time.ExperimentalTime
8 | import kotlin.time.TimeSource
9 |
10 | suspend fun await() = suspendCoroutine{ cont ->
11 | // if (true) cont.resumeWith()
12 | thread {
13 | Thread.sleep(1000)
14 | cont.resume(Unit)
15 | }
16 | }
17 |
18 | @ExperimentalTime
19 | suspend fun main() {
20 | mutableMapOf().remove(1)
21 | val time = TimeSource.Monotonic.markNow()
22 | await()
23 | await()
24 | await()
25 | println("elapsed ${time.elapsedNow()}")
26 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/SharedFlowMutableList.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableSharedFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 |
12 | val state = MutableSharedFlow>(replay = 1)
13 |
14 | val data = mutableListOf()
15 |
16 | coroutineScope {
17 | launch {
18 | while (true) {
19 | data.add(0)
20 | delay(1000)
21 | state.emit(data)
22 | }
23 | }
24 |
25 | state.collect {
26 | log("collected $it")
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/Test.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | fun maxDistance(nums1: IntArray, nums2: IntArray): Int {
4 | var max = 0
5 |
6 | for (i in nums1.indices) {
7 | val target = nums1[i]
8 |
9 | var lo = i
10 | var hi = nums2.lastIndex
11 |
12 | while (lo <= hi) {
13 | val mi = lo + (hi - lo) / 2
14 | if (nums2[mi] < target) {
15 | hi = mi - 1
16 | } else if (nums2[mi] > target) {
17 | lo = mi + 1
18 | } else {
19 | lo++
20 | }
21 | }
22 |
23 | max = Math.max(max, lo)
24 | }
25 |
26 | return max
27 | }
28 |
29 | fun main() {
30 | maxDistance(intArrayOf(55,30,5,4,2), intArrayOf(100,20,10,10,5)).also { println(it) }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/CancelFlowByException.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.CancellationException
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.flow
9 | import kotlinx.coroutines.launch
10 |
11 | suspend fun doWork() {
12 | delay(1000)
13 | throw CancellationException()
14 | }
15 |
16 | suspend fun main() {
17 | val flow = flow {
18 | emit(1)
19 | delay(1000)
20 | emit(2)
21 | emit(3)
22 | doWork()
23 | }
24 |
25 | coroutineScope {
26 | launch {
27 | flow.collect {
28 | log("collected $it")
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/client.kt:
--------------------------------------------------------------------------------
1 | package io
2 |
3 | import io.ktor.client.*
4 | import io.ktor.client.engine.cio.*
5 | import io.ktor.client.request.*
6 | import io.ktor.util.*
7 | import kotlinx.coroutines.coroutineScope
8 | import kotlinx.coroutines.launch
9 | import kotlin.system.measureTimeMillis
10 |
11 | @KtorExperimentalAPI
12 | suspend fun main() {
13 | val client = HttpClient(CIO)
14 |
15 | val time = measureTimeMillis {
16 | coroutineScope {
17 | repeat(1000) {
18 | launch {
19 | val result = client.get("http://localhost:8080/test?id=$it")
20 | println("${Thread.currentThread().name}: received res $result")
21 | }
22 | }
23 | }
24 | }
25 |
26 | println("spent $time")
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/DeadlockDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.launch
6 | import kotlinx.coroutines.sync.Mutex
7 |
8 | suspend fun main() {
9 | val s1 = Mutex()
10 | val s2 = Mutex()
11 |
12 | repeat(5) {
13 | coroutineScope {
14 | launch {
15 | s1.lock()
16 | delay(100)
17 | println("doing stuff in s1")
18 | s2.lock()
19 | s1.unlock()
20 | s2.unlock()
21 | }
22 |
23 | launch {
24 | s2.lock()
25 | delay(100)
26 | println("doing stuff in s2")
27 | s1.lock()
28 | s1.unlock()
29 | s2.unlock()
30 | }
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/backtrack/46_Permutation.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.backtrack
2 |
3 | import algorithms.TracingDeepRecursiveFunction
4 | import algorithms.invoke
5 |
6 | suspend fun main() {
7 | val arr = listOf(1, 2, 3)
8 | val result = mutableListOf>()
9 | val list = mutableListOf()
10 |
11 | val permute = TracingDeepRecursiveFunction, Unit> f@{
12 | if (list.size == arr.size) {
13 | result += list.toList()
14 | return@f
15 | }
16 |
17 | for (n in arr) {
18 | if (n in list) continue
19 | list += n
20 | callRecursive(list.toList()) // parameter only for tracing
21 | list.removeAt(list.lastIndex)
22 | }
23 | }
24 |
25 | permute(list)
26 | println(result)
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/backtrack/22_GenerateParenthesis.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.backtrack
2 |
3 | private fun gen(
4 | left: Int, right: Int, str: String,
5 | depth: Int,
6 | block: (String) -> Unit,
7 | ) {
8 | repeat(depth * 4) {
9 | print(" ")
10 | }
11 | print("($left, $right, \"$str\")")
12 | if (left == 0 && right == 0) {
13 | block(str)
14 | print(" // collect: $str\n")
15 | return
16 | }
17 | print("\n")
18 | val nextDepth = depth + 1
19 | if (left > 0) gen(left - 1, right + 1, str + '(', nextDepth, block)
20 | if (right > 0) gen(left, right - 1, str + ')', nextDepth, block)
21 | }
22 |
23 | fun main() {
24 | val result = mutableListOf()
25 |
26 | gen(3, 0, "", 0) { result += it }
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/ContextElementDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.CoroutineExceptionHandler
4 | import kotlinx.coroutines.CoroutineName
5 | import kotlinx.coroutines.Dispatchers
6 | import kotlin.coroutines.Continuation
7 | import kotlin.coroutines.ContinuationInterceptor
8 | import kotlin.coroutines.CoroutineContext
9 |
10 | fun main() {
11 | (CoroutineName("Coco") + Dispatchers.IO).also { it: CoroutineContext ->
12 | println(it[CoroutineName] == CoroutineName("Coco")) // true
13 | println(it[ContinuationInterceptor] == Dispatchers.IO) // true
14 | }
15 |
16 | (CoroutineName("foo") + CoroutineName("bar")).also { it: CoroutineContext ->
17 | println(it[CoroutineName] == CoroutineName("bar")) // true
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/GoStyleCancelDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.ExperimentalCoroutinesApi
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.channels.ReceiveChannel
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.launch
8 | import kotlinx.coroutines.runBlocking
9 |
10 | @ExperimentalCoroutinesApi
11 | suspend fun work(done: ReceiveChannel) {
12 | while (true) {
13 | if (done.isClosedForReceive) break
14 | println("working...")
15 | delay(1000)
16 | }
17 | }
18 |
19 | @ExperimentalCoroutinesApi
20 | fun main() = runBlocking{
21 | val c = Channel()
22 |
23 | launch {
24 | work(c)
25 | }
26 |
27 | delay(5000)
28 | c.close()
29 |
30 | Unit
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/FlowDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.ExperimentalCoroutinesApi
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.*
6 | import kotlinx.coroutines.launch
7 | import kotlinx.coroutines.runBlocking
8 | import kotlin.concurrent.thread
9 |
10 | fun main() = runBlocking{
11 | // flowOf(1, 2, 3).map { it * 2 }.filter { it % 2 == 0 }
12 |
13 | val flow = MutableStateFlow(1)
14 |
15 | launch {
16 | flow.collect {
17 | println(it)
18 |
19 | }
20 | }
21 |
22 | launch {
23 | delay(1000)
24 | flow.value = 10
25 | }
26 |
27 | launch {
28 | flow.collect {
29 | println(it)
30 | }
31 | }
32 |
33 |
34 | thread(isDaemon = true) {
35 | println("hi")
36 | }
37 |
38 | Unit
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/StateFlowWithCombine.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.GlobalScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableStateFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.combine
9 | import kotlinx.coroutines.flow.flow
10 | import kotlinx.coroutines.launch
11 |
12 | suspend fun main() {
13 | val state = MutableStateFlow(1)
14 |
15 | val flow = flow {
16 | delay(1000); emit("a")
17 | delay(1000); emit("b")
18 | }
19 |
20 | GlobalScope.launch {
21 | delay(5000)
22 | state.emit(2)
23 | }
24 |
25 | flow.combine(state) { i1, _ ->
26 | i1
27 | }.collect {
28 | log("collected flow: $it, state: ${state.value}")
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/io/retrofit.kt:
--------------------------------------------------------------------------------
1 | package io
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.launch
5 | import retrofit2.Retrofit
6 | import retrofit2.create
7 | import retrofit2.http.GET
8 | import retrofit2.http.Query
9 |
10 | interface TestService {
11 |
12 | @GET("/test")
13 | suspend fun testApi(@Query("id") id: Int)
14 | }
15 |
16 | suspend fun main() {
17 |
18 | val retrofit = Retrofit.Builder()
19 | .baseUrl("http://localhost:8080")
20 | .build()
21 |
22 | val service = retrofit.create()
23 |
24 | coroutineScope {
25 | repeat(100) {
26 | launch {
27 | service.testApi(it)
28 | val result = ""
29 | println("${Thread.currentThread().name}: received res $result")
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/NestedCallCancelDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 | import kotlin.time.Duration
6 | import kotlin.time.ExperimentalTime
7 |
8 | @ExperimentalTime
9 | object NestedCallCancelDemo {
10 | suspend fun foo() {
11 | try {
12 | bar()
13 | } catch (e: CancellationException) {
14 | println("caught $e")
15 | }
16 | }
17 |
18 | suspend fun bar() {
19 | println(coroutineContext.isActive)
20 | delay(Duration.INFINITE)
21 | }
22 | }
23 |
24 | @ExperimentalTime
25 | suspend fun main() {
26 | val job = GlobalScope.launch {
27 | NestedCallCancelDemo.foo()
28 | }
29 |
30 | job.cancelAndJoin()
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/StateFlowWithListDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.Flow
6 | import kotlinx.coroutines.flow.MutableStateFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 | val _state = MutableStateFlow(listOf(0))
12 | val flow: Flow> = _state
13 | coroutineScope {
14 | launch {
15 | delay(1000)
16 | _state.value = listOf(1)
17 | delay(1000)
18 | _state.value = listOf(2)
19 | delay(1000)
20 | _state.value = listOf(3)
21 |
22 | _state.value += 1
23 | _state.value -= 1
24 | }
25 |
26 | flow.collect {
27 | println(it)
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/serialization/SerializableDemo.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.Dispatchers
2 | import kotlinx.coroutines.GlobalScope
3 | import kotlinx.coroutines.channels.Channel
4 | import kotlinx.coroutines.plus
5 | import java.io.File
6 | import java.io.ObjectOutputStream
7 | import java.io.Serializable
8 |
9 | data class Value(val value: T) : Serializable
10 |
11 | data class Person(val name: String, val gender: String = "abc") : Serializable {
12 | companion object {
13 | @JvmStatic private val serialVersionUID = 1381488341778288004
14 | }
15 | }
16 |
17 | suspend fun main() {
18 | Channel { }
19 | GlobalScope + Dispatchers.IO
20 | val p = Person("Peter", "M")
21 |
22 | val fs = File("test.bin").outputStream()
23 | ObjectOutputStream(fs).use {
24 | it.writeObject(p)
25 | }
26 | }
--------------------------------------------------------------------------------
/src/test/kotlin/HookTest.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.GlobalScope
2 | import kotlinx.coroutines.launch
3 | import kotlinx.html.*
4 |
5 | fun main() {
6 | val consumer = TestConsumer()
7 | val (counter, setCount) = useState(0)
8 | val (switch, setSwitch) = useState(true)
9 | val (data, setData) = useState(listOf(1, 2, 3))
10 |
11 | HTML(mapOf(), consumer).apply {
12 | body {
13 | p(classes = "foo bar") { +"counter is $counter" }
14 | div {
15 | ul {
16 | for (i in data) li { +i.toString() }
17 | }
18 | }
19 | if (switch) p { +"Hello World!" }
20 | }
21 | }
22 |
23 | GlobalScope.launch {
24 | setCount(1)
25 | }
26 | }
27 |
28 |
29 | fun useState(value: T): Pair Unit> {
30 |
31 | return value to { newValue: T -> Unit }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/CoroutineScopeDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import kotlin.coroutines.coroutineContext
5 |
6 | fun test1(scope: CoroutineScope) {
7 | scope.launch {
8 | delay(2000)
9 | throw IllegalStateException("whoops in test 1")
10 | }
11 | }
12 |
13 | fun test2(scope: CoroutineScope) {
14 | scope.launch {
15 | while (true) {
16 | delay(500)
17 | log("test2: I'm working")
18 | }
19 | }
20 | }
21 |
22 | suspend fun sayHi() {
23 | println(coroutineContext)
24 | }
25 |
26 | suspend fun doNotDoThis() {
27 | CoroutineScope(coroutineContext).launch {
28 | println("delaying")
29 | delay(1000)
30 | println("hello")
31 | }
32 | }
33 |
34 | suspend fun main() {
35 | coroutineScope {
36 | doNotDoThis()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/CancelJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import coroutine.blogpost.structuredconcurrency.printAsTree
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.launch
7 | import kotlin.time.Duration.Companion.INFINITE
8 | import kotlin.time.ExperimentalTime
9 |
10 | @ExperimentalTime
11 | suspend fun main() = coroutineScope {
12 | val job =
13 | launch {
14 | launch {
15 | launch { delay(INFINITE) }
16 | launch { delay(INFINITE) }
17 | }
18 | launch {
19 | launch { delay(INFINITE) }
20 | launch { delay(INFINITE) }
21 | }
22 | }
23 |
24 | delay(500)
25 | job.printAsTree()
26 | job.cancel()
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/caching/StateFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.caching
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.launch
8 |
9 | private var n = 0
10 | suspend fun someHeavyWeightCalculation(): Int {
11 | delay(1000)
12 | return (n++)
13 | }
14 |
15 | suspend fun main() {
16 | val state = MutableStateFlow(0)
17 |
18 | GlobalScope.launch {
19 | while (true) {
20 | state.value = someHeavyWeightCalculation().also { println("f calculated $it") }
21 | delay(1000)
22 | }
23 | }
24 |
25 | state.collect {
26 | println("consumer collected: $it")
27 | println("consumer sleeping a while")
28 | delay(2000)
29 | }
30 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/ConvertToSharedFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.*
7 | import kotlinx.coroutines.launch
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.seconds
10 |
11 | @ExperimentalTime
12 | suspend fun main() {
13 | suspend fun callSomeApi(): String {
14 | delay(1.seconds)
15 | return "hello world".also { log("calculated result: $it") }
16 | }
17 | coroutineScope {
18 | val flow = flow {
19 | emit(callSomeApi())
20 | }.shareIn(this, SharingStarted.Lazily)
21 |
22 |
23 | repeat(5) {
24 | launch {
25 | flow.collect {
26 | log("collected $it")
27 | }
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/fp/ArrowEitherDemo.kt:
--------------------------------------------------------------------------------
1 | package fp
2 |
3 | import arrow.core.Either
4 | import arrow.core.computations.either
5 | import arrow.core.flatMap
6 | import arrow.core.left
7 | import arrow.core.right
8 | import fp.ArrowEitherDemo.uploadImage
9 | import fp.ArrowEitherDemo.uploadVideo
10 | import kotlin.random.Random
11 |
12 | object ArrowEitherDemo {
13 | fun uploadImage(): Either =
14 | if (Random.nextBoolean()) NetworkUnstable.left() else "xxx".right()
15 |
16 | fun uploadVideo(): Either =
17 | if (Random.nextBoolean()) NetworkUnstable.left() else "xxx".right()
18 | }
19 |
20 | suspend fun main() {
21 | val result = either> {
22 | listOf(uploadImage().bind(), uploadVideo().bind())
23 | }
24 | println(result)
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/CancelCouroutineByException.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.flow.collect
5 | import kotlinx.coroutines.flow.flow
6 |
7 | fun main() = runBlocking {
8 | val job = GlobalScope.launch {
9 | delay(1000)
10 | throw CancellationException()
11 | }
12 |
13 | job.join()
14 |
15 | coroutineScope {
16 | launch {
17 | delay(1000)
18 | log("delayed 1000")
19 | throw CancellationException()
20 | }
21 | }
22 |
23 | coroutineScope {
24 | val f = flow {
25 | emit(1)
26 | delay(1000)
27 | emit(2)
28 | delay(1000)
29 | throw CancellationException()
30 | }
31 | coroutineScope {
32 | f.collect {
33 | log("collected $it")
34 | }
35 | }
36 | }
37 |
38 | Unit
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/SharedFlowDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableSharedFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 | val state = MutableSharedFlow(replay = 1)
12 |
13 | coroutineScope {
14 | launch {
15 | delay(2000)
16 | var i = 0
17 | while (true) {
18 | val valueToEmit = (i++).also { log("preparing to emit $it") }
19 | state.emit(valueToEmit)
20 | }
21 | }
22 |
23 | launch {
24 | state.collect {
25 | log("received $it")
26 | log("cache is ${state.replayCache}")
27 | delay(1000)
28 | }
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/TakeOperatorDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableSharedFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.first
9 | import kotlinx.coroutines.flow.take
10 | import kotlinx.coroutines.launch
11 |
12 | suspend fun main() {
13 | val flow = MutableSharedFlow(1)
14 | coroutineScope {
15 | launch {
16 | delay(500)
17 | flow.emit(Unit)
18 | }
19 |
20 | launch {
21 | flow.first()
22 | log("1: collect done")
23 | }
24 |
25 | launch {
26 | delay(1000)
27 | flow.first()
28 | log("2: collect done")
29 | }
30 | listOf(1, 2, 3).subList(0, 5)
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/JobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.InternalCoroutinesApi
5 | import kotlinx.coroutines.Job
6 | import kotlinx.coroutines.launch
7 | import org.litote.kmongo.index
8 |
9 | @InternalCoroutinesApi
10 | suspend fun main() {
11 | val job = GlobalScope.launch {
12 | launch {
13 | launch { }
14 | launch { }
15 | }
16 | launch {
17 | launch { }
18 | launch { }
19 | }
20 | }.apply { join() }
21 |
22 | printJobTree(job)
23 | }
24 |
25 | fun printJobTree(job: Job, builder: StringBuilder = StringBuilder()) {
26 | println(builder.toString() + job)
27 | job.children.forEach {
28 | printJobTree(it, builder.append(" "))
29 | }
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/src/test/kotlin/DynamicTest.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.html.*
2 |
3 | fun template() {
4 |
5 | }
6 |
7 | fun main() {
8 | val consumer = TestConsumer()
9 | val data = listOf(1, 2, 3)
10 | var counter = 0
11 | var switch = true
12 | HTML(mapOf(), consumer).apply {
13 | body {
14 | p(classes = "foo bar") {
15 | +"counter is ${dynamic(counter)}"
16 | }
17 | div {
18 | ul {
19 | for (i in dynamic(data)) {
20 | li { +i.toString() }
21 | }
22 | }
23 | }
24 | if (dynamic(switch)) {
25 | p { +"Hello World!" }
26 | }
27 | }
28 | }
29 | counter++
30 | switch = false
31 | }
32 |
33 | fun HTMLTag.dynamic(value: T): T {
34 | (consumer as? TestConsumer)?.apply {
35 | registerDynamic(value)
36 | }
37 |
38 | return value
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/CancelJobFiboDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import kotlinx.coroutines.*
4 |
5 | suspend fun main() {
6 | val job = GlobalScope.launch(Dispatchers.IO) {
7 | for (i in 0..50) {
8 | // 除了 return 之外还可以抛 `CancellationException`
9 | // 协程库提供的 `ensureActive` 封装了这一方法
10 | // 另外也可以使用 `yield`
11 | // -----下面这些写法都可以-----
12 | // if (!isActive) throw CancellationException()
13 | // ensureActive()
14 | // yield()
15 | if (!isActive) return@launch
16 | println(fibonacci(i))
17 | }
18 | }
19 | delay(100)
20 | // 取消 job 并等待,避免 jvm 直接退出
21 | job.cancelAndJoin()
22 | }
23 |
24 | // deliberately slow fibonacci
25 | fun fibonacci(n: Int): Int = if (n <= 1)
26 | n else fibonacci(n - 1) + fibonacci(n - 2)
27 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/ChannelToFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.flow.*
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun main() {
11 | val refreshRequest = MutableStateFlow(0)
12 | val search = flow {
13 | delay(1000); emit("foo")
14 | delay(1000); emit("bar")
15 | }
16 |
17 | coroutineScope {
18 | launch {
19 | delay(5000)
20 | delay(1000); refreshRequest.value += 1
21 | delay(1000); refreshRequest.value += 1
22 | }
23 |
24 | search.combine(refreshRequest) { query, _ ->
25 | delay(500)
26 | "search result for $query"
27 | }.collect {
28 | log("collected $it")
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/ContinuationDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import io.ktor.client.utils.*
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.launch
6 | import java.io.File
7 | import kotlin.coroutines.*
8 | import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
9 |
10 | fun run(block: suspend () -> Unit) {
11 | // (block as Function1
12 |
13 | }
14 |
15 | // https://github.com/arrow-kt/arrow-fx/tree/master/arrow-fx-coroutines
16 | object ContinuationDemo {
17 | suspend fun test(): Int = 1
18 | suspend fun fail(): Int = TODO()
19 |
20 | }
21 |
22 |
23 | fun main() {
24 | val cont = ContinuationDemo::test.createCoroutine(Continuation(EmptyCoroutineContext, ::println))
25 | cont.resume(Unit)
26 |
27 |
28 | ContinuationDemo::fail.startCoroutine(Continuation(EmptyCoroutineContext, ::println))
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/kmongo.kt:
--------------------------------------------------------------------------------
1 | import com.mongodb.client.model.UpdateOptions
2 | import org.litote.kmongo.*
3 |
4 | class Shop(
5 | val meta: Meta
6 | )
7 |
8 | class Meta(
9 | val status: Int
10 | )
11 |
12 | fun getShop(): Shop = TODO()
13 |
14 | fun main() {
15 |
16 | Shop::meta / Meta::status gt 1
17 | Meta::status gt 1
18 | // Meta::status gt "1"
19 |
20 | val client = KMongo.createClient() //get com.mongodb.MongoClient new instance
21 | val database = client.getDatabase("test") //normal java driver usage
22 | val col = database.getCollection() //KMongo extension method
23 | //here the name of the collection by convention is "jedi"
24 | //you can use getCollection("otherjedi") if the collection name is different
25 |
26 | val shop = getShop()
27 |
28 |
29 |
30 | col.updateOne(shop, UpdateOptions().bypassDocumentValidation(true) )
31 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/StateFlowWrappedMutableListDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.launch
8 |
9 | sealed class State {
10 | data class Success(val data: List)
11 | data class Error(val error: Throwable) : State()
12 | }
13 |
14 | suspend fun main() {
15 | val list = mutableListOf(0)
16 | val state = MutableStateFlow(State.Success(list))
17 |
18 | coroutineScope {
19 | launch {
20 | list.add(1)
21 | state.value = State.Success(list)
22 | delay(1000)
23 | list.add(2)
24 | state.value = State.Success(list)
25 | delay(1000)
26 | }
27 |
28 | state.collect {
29 | println(it)
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/LazyCoroutine.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.flow.MutableSharedFlow
6 | import kotlinx.coroutines.flow.collect
7 | import kotlin.coroutines.CoroutineContext
8 |
9 |
10 | suspend fun main() {
11 | log("starting...")
12 |
13 | val jobs = MutableSharedFlow(replay = 5)
14 |
15 | // val jobs = Channel(capacity = 1)
16 |
17 | coroutineScope {
18 |
19 | repeat(5) {
20 | val job: Job = launch(start = CoroutineStart.LAZY, context = coroutineContext) {
21 | log("job $it started")
22 | delay(2000)
23 | log("job $it end")
24 | }
25 | jobs.emit(job)
26 | }
27 |
28 | log("prepare to collect")
29 | jobs.collect {
30 | log("collected $it")
31 | it.start()
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/105_ConstructTree.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | class TreeNode(
4 | val `val`: Int,
5 | var left: TreeNode? = null,
6 | var right: TreeNode? = null,
7 | )
8 |
9 | fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
10 | fun buildTree(lo: Int, hi: Int): TreeNode? {
11 | if (hi < lo) return null
12 | val rootValue = preorder[lo]
13 | val node = TreeNode(rootValue)
14 | val iRootIndex = inorder.indexOf(rootValue)
15 | val leftSize = iRootIndex
16 | val rightSize = hi - iRootIndex
17 | node.left = buildTree(lo + 1, lo + leftSize)
18 | node.right = buildTree(lo + leftSize + 1, lo + leftSize + rightSize)
19 | return node
20 | }
21 |
22 | return buildTree(0, preorder.lastIndex)
23 | }
24 |
25 | fun main() {
26 | buildTree(intArrayOf(3, 9, 20, 15, 7), intArrayOf(9, 3, 15, 20, 7))
27 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/jcip/CatchCancellationExceptionDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency.jcip
2 |
3 | import kotlinx.coroutines.coroutineScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.launch
6 | import kotlinx.coroutines.runBlocking
7 | import kotlin.random.Random
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.TimeSource
10 |
11 | suspend fun fetchData(): Int {
12 | delay(1000)
13 | if (Random.nextInt(0, 10) < 2)
14 | error("whoops")
15 | return 1
16 | }
17 |
18 | @OptIn(ExperimentalTime::class)
19 | fun main() = runBlocking {
20 | val now = TimeSource.Monotonic.markNow()
21 | val job = launch {
22 | runCatching {
23 | fetchData()
24 | }
25 |
26 | // Pretend we continue to do other work...
27 | while (true) {
28 | }
29 | }
30 |
31 | delay(200)
32 | job.cancel()
33 | println(now.elapsedNow())
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/channel/SuspendUntilValue.kt:
--------------------------------------------------------------------------------
1 | package coroutine.channel
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.launch
8 |
9 | suspend fun main() {
10 | val channel = Channel()
11 |
12 | suspend fun Channel.waitUntil(value: Boolean) {
13 | for (v in this) {
14 | if (v == value) break
15 | }
16 | }
17 |
18 | coroutineScope {
19 | launch {
20 | channel.waitUntil(true)
21 | log("received true")
22 | }
23 |
24 | launch {
25 | log("sending false")
26 | channel.send(false)
27 | delay(500)
28 | log("sending false")
29 | channel.send(false)
30 | delay(500)
31 | log("sending true")
32 | channel.send(true)
33 | }
34 | }
35 |
36 | }
--------------------------------------------------------------------------------
/src/main/kotlin/excercise/LazyListImpl.kt:
--------------------------------------------------------------------------------
1 | package excercise
2 |
3 | //interface Sequence {
4 | // fun emit(value: Int)
5 | //}
6 |
7 | interface LazyList {
8 | fun collect(block: (Int) -> Unit)
9 | }
10 |
11 | class LazyListImpl(
12 | val list: List
13 | ) : LazyList {
14 |
15 | override fun collect(block: (Int) -> Unit) {
16 | list.forEach(block)
17 | }
18 | }
19 |
20 | fun LazyList.map(mapper: (Int) -> Int): LazyList {
21 | val self = this
22 | return object : LazyList {
23 | override fun collect(block: (Int) -> Unit) {
24 | self.collect {
25 | block(mapper(it))
26 | }
27 | }
28 | }
29 | }
30 |
31 | fun main() {
32 | val list = LazyListImpl(listOf(1, 2, 3, 4, 5))
33 | list
34 | .map { value ->
35 | (value * 2).also { println("mapped $it") }
36 | }
37 | .collect {
38 | println("collected $it")
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/Cancel.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.Flow
6 | import kotlinx.coroutines.flow.MutableStateFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.flow
9 | import kotlinx.coroutines.launch
10 |
11 | fun getFlow() = flow {
12 | var n = 0
13 | while (true) {
14 | emit(n++)
15 | delay(1000)
16 | }
17 | }
18 |
19 | suspend fun main() {
20 | val state = MutableStateFlow(0)
21 |
22 | val job = GlobalScope.launch {
23 | getFlow().collect {
24 | state.value = it
25 | }
26 | }
27 |
28 | GlobalScope.launch {
29 | state.collect {
30 | println("consumer collected: $it")
31 | }
32 | }
33 |
34 | GlobalScope.launch {
35 | delay(5000)
36 | job.cancel()
37 |
38 | state.value = 100
39 | }.join()
40 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/job/ParentChildByContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency.job
2 |
3 | import arrow.core.extensions.either.applicativeError.catch
4 | import kotlinx.coroutines.*
5 | import kotlin.coroutines.coroutineContext
6 |
7 | suspend fun sayHelloWorldInContext(): String {
8 | val a = GlobalScope.async(coroutineContext) {
9 | delay(500); error("whoops")
10 | println("a running")
11 | "Hello "
12 | }
13 | val b = GlobalScope.async(coroutineContext) {
14 | try {
15 | delay(1000)
16 | println("b running")
17 | " World!"
18 | } catch (e: Throwable) {
19 | println(e)
20 | }
21 | }
22 | return a.await() + b.await()
23 | }
24 |
25 | fun main() = runBlocking {
26 | val job = launch {
27 | println(sayHelloWorldInContext())
28 | }
29 | delay(600)
30 | job.cancelAndJoin()
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/MarkovGenerator.kt:
--------------------------------------------------------------------------------
1 | package algorithms
2 |
3 | import kotlin.random.Random
4 |
5 | class MarkovGenerator(private val k: Int, text: String) {
6 | private val ngramStore = mutableMapOf>().apply {
7 | val ngramsSequence = text.splitToSequence("")
8 | .filterNot { it.isBlank() }
9 | .windowed(k) { it.joinToString("") }
10 | ngramsSequence.windowed(2)
11 | .forEach {
12 | getOrPut(it[0]) { mutableListOf() }.add(it[1].last().toString())
13 | }
14 | }
15 |
16 | fun generate(length: Int): String = buildString {
17 | val keys = ngramStore.keys.toList()
18 | var cur = keys[Random.nextInt(0, ngramStore.size - 1)].also { append(it) }
19 | var size = 0
20 | while (size < length) {
21 | size += k
22 | cur = cur.drop(1) + ngramStore[cur]!!.random().also { append(it) }
23 | }
24 | }
25 | }
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/CancelingFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.ExperimentalCoroutinesApi
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.collect
7 | import kotlinx.coroutines.flow.flatMapLatest
8 | import kotlinx.coroutines.flow.flow
9 |
10 | @ExperimentalCoroutinesApi
11 | suspend fun main() {
12 | fun searchResults(query: String) = flow {
13 | var page = 1
14 | while (true) {
15 | delay(500)
16 | emit("result for $query, page ${page++}")
17 | }
18 | }
19 |
20 | fun userSearchQuery() = flow {
21 | val interval = (1000..3000)
22 | var query = 1
23 | while (true) {
24 | delay(interval.random().toLong())
25 | emit("user query: ${query++}".also { log(it) })
26 | }
27 | }
28 |
29 | userSearchQuery()
30 | .flatMapLatest { searchResults(it) }
31 | .collect { log(it) }
32 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/132pattern.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | import java.util.*
4 | import kotlin.math.max
5 |
6 | fun find132pattern(nums: IntArray): Boolean {
7 | val stack: Deque = ArrayDeque()
8 | var three = Int.MIN_VALUE
9 |
10 | for (i in nums.indices.reversed()) {
11 | val one = nums[i]
12 | if (one < three) {
13 | println("result is ${listOf(one, stack.peek(), three)}")
14 | return true
15 | }
16 | while (!stack.isEmpty() && stack.peek() < one) {
17 | three = max(stack.pop(), three)
18 | }
19 | // We're outside the while loop, stack.peek() >= one
20 | stack.push(one)
21 | }
22 |
23 | return false
24 | }
25 |
26 | fun main() {
27 | // find132pattern(intArrayOf(1, 0, 1, -4, -3)).also { println(it) }
28 | find132pattern(intArrayOf(3, 1, 4, 2)).also { println(it) }
29 | find132pattern(intArrayOf(-1, 3, 2, 0)).also { println(it) }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/QuickSort.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | fun quickSort(arr: IntArray) {
4 | fun swap(i: Int, j: Int) {
5 | val temp = arr[j]
6 | arr[j] = arr[i]
7 | arr[i] = temp
8 | }
9 |
10 | fun partition(lo: Int, hi: Int): Int {
11 | var i: Int = lo
12 | var j: Int = hi + 1
13 | val pivotValue = arr[lo]
14 | while (true) {
15 | while (arr[++i] < pivotValue) if (i == hi) break
16 | while (arr[--j] > pivotValue) if (j == lo) break
17 | if (i >= j) break
18 | swap(i, j)
19 | }
20 | swap(lo, j)
21 | return j
22 | }
23 |
24 | fun sort(lo: Int, hi: Int) {
25 | if (hi <= lo) return
26 | val pivot = partition(lo, hi)
27 | sort(lo, pivot - 1)
28 | sort(pivot + 1, hi)
29 | }
30 |
31 | sort(0, arr.lastIndex)
32 | }
33 |
34 | fun main() {
35 | val arr = intArrayOf(5, 1, 4, 2, 3)
36 | quickSort(arr)
37 | println(arr.toList())
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/backtrack/22_GenerateParenthesisDeepRecursive.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("ConvertToStringTemplate")
2 |
3 | package algorithms.leetcode.backtrack
4 |
5 | import algorithms.TracingDeepRecursiveFunction
6 | import algorithms.invoke
7 |
8 | data class Param(
9 | val left: Int,
10 | val right: Int,
11 | val str: String,
12 | ) {
13 | override fun toString(): String {
14 | return "$left, $right, str=$str"
15 | }
16 | }
17 |
18 | suspend fun main() {
19 | val result = mutableListOf()
20 | val generateParenthesis = TracingDeepRecursiveFunction { (left, right, str) ->
21 | if (left == 0 && right == 0) result += str
22 | if (left > 0) callRecursive(Param(left - 1, right + 1, str + '('))
23 | if (right > 0) callRecursive(Param(left, right - 1, str + ')'))
24 | }
25 |
26 | val param = Param(3, 0, "")
27 | generateParenthesis(param)
28 | println(result)
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/src/main/kotlin/ktor/HtmlDemo.kt:
--------------------------------------------------------------------------------
1 | import io.ktor.application.*
2 | import io.ktor.html.*
3 | import io.ktor.http.*
4 | import io.ktor.response.*
5 | import io.ktor.routing.*
6 | import io.ktor.server.engine.*
7 | import io.ktor.server.netty.*
8 | import kotlinx.html.body
9 | import kotlinx.html.h1
10 |
11 | fun main(args: Array) {
12 | val server = embeddedServer(Netty, port = 8080) {
13 | routing {
14 | get("/") {
15 | call.respondText("Hello World!", ContentType.Text.Plain)
16 | }
17 | get("/demo") {
18 | call.respondText("HELLO WORLD!")
19 | }
20 | get("/html") {
21 | call.respondHtml {
22 | body {
23 | h1 { +"Hello World!" }
24 | }
25 | }
26 | }
27 | }
28 | }
29 | server.start(wait = true)
30 | }
31 |
32 |
33 |
--------------------------------------------------------------------------------
/src/main/kotlin/ktorm/KtormPgDemo.kt:
--------------------------------------------------------------------------------
1 | package ktorm
2 |
3 | import ktorm.User.primaryKey
4 | import org.ktorm.database.Database
5 | import org.ktorm.dsl.Query
6 | import org.ktorm.dsl.forEach
7 | import org.ktorm.dsl.from
8 | import org.ktorm.dsl.select
9 | import org.ktorm.schema.Table
10 | import org.ktorm.schema.int
11 | import org.ktorm.support.postgresql.PostgreSqlDialect
12 | import org.ktorm.support.postgresql.textArray
13 |
14 |
15 | val pg = Database.connect(
16 | url = "jdbc:postgresql://localhost:49156/postgres",
17 | user = "postgres",
18 | password = "123456",
19 | dialect = PostgreSqlDialect()
20 | )
21 |
22 | object PgUser : Table("users") {
23 | val id = int("id")
24 | val friends = textArray("friends")
25 | }
26 |
27 |
28 | fun main() {
29 | val q: Query = pg.from(PgUser).select(PgUser.id, PgUser.friends)
30 | q.forEach {
31 | println("${it[PgUser.id]}, ${it[PgUser.friends]}")
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/ErrorPropogation.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.async
5 | import kotlinx.coroutines.launch
6 | import kotlinx.coroutines.runBlocking
7 |
8 | fun main() = runBlocking {
9 | val job = GlobalScope.launch { // root coroutine with launch
10 | println("Throwing exception from launch")
11 | throw IndexOutOfBoundsException() // Will be printed to the console by Thread.defaultUncaughtExceptionHandler
12 | }
13 | job.join()
14 | println("Joined failed job")
15 | val deferred = GlobalScope.async { // root coroutine with async
16 | println("Throwing exception from async")
17 | throw ArithmeticException() // Nothing is printed, relying on user to call await
18 | }
19 | // try {
20 | // deferred.await()
21 | // println("Unreached")
22 | // } catch (e: ArithmeticException) {
23 | // println("Caught ArithmeticException")
24 | // }
25 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/LoadMoreRequestDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.MutableSharedFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.take
9 | import kotlinx.coroutines.flow.takeWhile
10 | import kotlinx.coroutines.launch
11 |
12 | suspend fun main() {
13 | val loadMoreRequest = MutableSharedFlow()
14 | coroutineScope {
15 | launch {
16 | repeat(20) {
17 | delay(100)
18 | loadMoreRequest.emit(Unit)
19 | }
20 | }
21 |
22 | launch {
23 | while (true) {
24 | // loadMoreRequest.collect {
25 | // log("received event")
26 | // }
27 |
28 | loadMoreRequest.take(1).collect {
29 | log("received event")
30 | }
31 |
32 | log("calling api")
33 | delay(1000)
34 | }
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/InitStateFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.CoroutineScope
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.flow.MutableStateFlow
8 | import kotlinx.coroutines.flow.StateFlow
9 | import kotlinx.coroutines.flow.collect
10 | import kotlinx.coroutines.launch
11 |
12 | class Client {
13 | fun CoroutineScope.publish(): StateFlow {
14 | val state = MutableStateFlow(1)
15 | launch {
16 | // delay(1000)
17 | state.value = 2
18 | delay(1000)
19 | state.value = 3
20 | }
21 | return state
22 | }
23 |
24 | suspend fun publish2(flow: MutableStateFlow) {
25 |
26 | }
27 | }
28 |
29 | suspend fun main() {
30 | val client = Client()
31 | coroutineScope {
32 | val flow = with(client) { publish() }
33 | flow.collect {
34 | log("collected $it")
35 | }
36 | log("asdc")
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlowQ3.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.flow.*
6 |
7 | @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class)
8 | fun Flow.concurrentOnEach(
9 | scope: CoroutineScope,
10 | concurrency: Int = 10,
11 | block: suspend (T) -> Unit,
12 | ) = channelFlow {
13 | val chan = Channel(capacity = concurrency)
14 | scope.launch {
15 | for (item in chan) block(item)
16 | }
17 | collect {
18 | chan.send(it)
19 | send(it)
20 | }
21 | chan.close()
22 | }
23 |
24 | suspend fun main() {
25 | coroutineScope {
26 | flow {
27 | println("only once")
28 | repeat(20) {
29 | emit(it)
30 | }
31 | }
32 | .concurrentOnEach(this) {
33 | println("concurrent onEach: $it")
34 | }
35 | .collect {
36 | delay(500)
37 | println("onEach $it")
38 | }
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/main/kotlin/rx/RxApiDemo.kt:
--------------------------------------------------------------------------------
1 | package rx
2 |
3 | import io.reactivex.rxjava3.core.Observable
4 | import io.reactivex.rxjava3.core.ObservableTransformer
5 | import kotlin.random.Random
6 |
7 | data class ApiResponse(val code: Int, val data: String)
8 |
9 |
10 | fun generateResponse() = if (Random.nextBoolean())
11 | ApiResponse(0, "Hello") else ApiResponse(50000, "Hello")
12 |
13 | val apiHandler = ObservableTransformer { upstream ->
14 | upstream
15 | ?.flatMap {
16 | if (it.code != 0) Observable.error(IllegalArgumentException("Whoops"))
17 | else Observable.just(it)
18 | }
19 | ?.doOnError {
20 | println("caught error: $it")
21 | }
22 | }
23 |
24 | fun main() {
25 | Observable.create {
26 | it.onNext(generateResponse())
27 | }.compose(apiHandler)
28 | .doOnError { println("caught on ui: $it") }
29 | .retry(3)
30 | .onErrorComplete()
31 | .subscribe {
32 | println("success: received $it")
33 | }
34 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/continuation/CallDelayManuallyDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.continuation
2 |
3 | import kotlinx.coroutines.delay
4 | import java.util.concurrent.CountDownLatch
5 | import kotlin.coroutines.Continuation
6 | import kotlin.coroutines.CoroutineContext
7 | import kotlin.coroutines.EmptyCoroutineContext
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.TimeSource
10 |
11 | @ExperimentalTime
12 | fun main() {
13 | val delay: suspend (Long) -> Unit = ::delay
14 |
15 | @Suppress("UNCHECKED_CAST")
16 | val df = delay as Function2, Any>
17 |
18 | val now = TimeSource.Monotonic.markNow()
19 | val latch = CountDownLatch(1)
20 |
21 | df(1000, object : Continuation {
22 | override val context: CoroutineContext = EmptyCoroutineContext
23 |
24 | override fun resumeWith(result: Result) {
25 | println("resumed: $result, elapsed: ${now.elapsedNow()}")
26 | latch.countDown()
27 | }
28 | })
29 |
30 | latch.await()
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/toy/FlowImplDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow.toy
2 |
3 | import kotlinx.coroutines.InternalCoroutinesApi
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.Flow
6 | import kotlinx.coroutines.flow.FlowCollector
7 | import kotlinx.coroutines.flow.collect
8 |
9 |
10 | class FlowImpl(
11 | private val builder: suspend FlowCollector.() -> Unit
12 | ) : Flow {
13 |
14 | @OptIn(InternalCoroutinesApi::class)
15 | override suspend fun collect(collector: FlowCollector) = collector.builder()
16 | }
17 |
18 | fun Flow.map(block: suspend (value: T) -> R) = FlowImpl {
19 | collect { emit(block(it)) }
20 | }
21 |
22 | fun Flow.filter(block: suspend (value: T) -> Boolean) = FlowImpl {
23 | collect { if (block(it)) emit(it) }
24 | }
25 |
26 |
27 | suspend fun main() = FlowImpl { emit(1); emit(2) }
28 | .map { it * it }
29 | .filter {
30 | delay(1000)
31 | it % 2 == 0
32 | }
33 | .collect { println("collected $it") }
34 |
35 |
--------------------------------------------------------------------------------
/src/main/kotlin/ktorm/KtormDemo.kt:
--------------------------------------------------------------------------------
1 | package ktorm
2 |
3 | import io.ktor.util.*
4 | import org.ktorm.database.Database
5 | import org.ktorm.dsl.*
6 | import org.ktorm.schema.Table
7 | import org.ktorm.schema.int
8 | import org.ktorm.schema.varchar
9 | import org.ktorm.support.mysql.insertOrUpdate
10 |
11 | val database = Database.connect(
12 | url = "jdbc:mysql://api.beta.jojotu.cn:3306/jojotoo_test",
13 | user = "test",
14 | password = "a0a40zDod4HjM84t"
15 | )
16 |
17 | object User : Table("user") {
18 | val id = int("id").primaryKey()
19 | val name = varchar("user_nickname")
20 | val tel = varchar("user_tel_zone")
21 | val cityId = int("city_id")
22 | }
23 |
24 | fun main() {
25 | val q1 = database.from(User).select(User.id, User.name, User.tel)
26 | .limit(10, 10)
27 | val q2 = q1.where {
28 | User.cityId eq 1
29 | }
30 | println(q2.sql)
31 |
32 |
33 | val u1 = User.aliased("u1")
34 | val u2 = User.aliased("u2")
35 | database.from(u1)
36 |
37 | User.insertOrUpdate { }
38 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/jcip/MemoizerJcipDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency.jcip
2 |
3 | import java.util.concurrent.CancellationException
4 | import java.util.concurrent.ConcurrentHashMap
5 | import java.util.concurrent.Future
6 | import java.util.concurrent.FutureTask
7 |
8 | fun interface Computable {
9 | fun compute(arg: A): V
10 | }
11 |
12 | /**
13 | * Reference: JCIP Section 5.6
14 | */
15 | class Memoizer(
16 | private val c: Computable,
17 | ) : Computable {
18 |
19 | private val cache = ConcurrentHashMap>()
20 |
21 | override fun compute(arg: A): V {
22 | while (true) {
23 | var f: Future? = cache[arg]
24 | if (f == null) {
25 | val ft = FutureTask { c.compute(arg) }
26 | f = cache.putIfAbsent(arg, ft)
27 | if (f == null) {
28 | f = ft
29 | ft.run()
30 | }
31 | }
32 | try {
33 | return f.get()
34 | } catch (e: CancellationException) {
35 | cache.remove(arg, f)
36 | }
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/ContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlinx.coroutines.CoroutineName
4 | import kotlinx.coroutines.Job
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.launch
7 | import kotlin.coroutines.coroutineContext
8 | import kotlin.coroutines.resume
9 | import kotlin.coroutines.suspendCoroutine
10 |
11 |
12 | suspend fun main() {
13 | coroutineScope {
14 | // 在 Context 中添加 CoroutineName[Coco] 元素
15 | launch(CoroutineName("Coco")) {
16 | contextCheck()
17 | }
18 | }
19 | }
20 |
21 | // 调用链:foo->bar->baz
22 | suspend fun contextCheck() = bar()
23 | suspend fun bar() = baz()
24 | suspend fun baz() {
25 | // 在调用链中获取 Context 中的元素
26 | println(coroutineContext[CoroutineName])
27 |
28 | val context = coroutineContext[Job]
29 |
30 | suspendCoroutine {
31 | println(it.context === context)
32 | it.resume(Unit)
33 | }
34 |
35 | coroutineScope {
36 | launch {
37 | println(coroutineContext[CoroutineName])
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/caching/CachingFlowDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.caching
2 |
3 | import kotlinx.coroutines.GlobalScope
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.*
6 | import kotlinx.coroutines.launch
7 | import kotlinx.coroutines.runBlocking
8 |
9 | class Box(val value: Int)
10 |
11 |
12 | suspend fun main() {
13 |
14 | val data = mutableListOf()
15 |
16 | val flow = flow {
17 | println("start emitting")
18 | emit(Box(1))
19 | emit(Box(2))
20 | emit(Box(3))
21 | println("end emitting")
22 | }.cacheIn(data)
23 |
24 |
25 | flow.collect {
26 | println("1: $it")
27 | }
28 |
29 | println("data is $data")
30 |
31 | flow.collect {
32 | println("2: $it")
33 | }
34 | println("data is $data")
35 | }
36 |
37 | private fun Flow.cacheIn(mutableList: MutableList): Flow = flow {
38 | if (mutableList.isNotEmpty()) {
39 | mutableList.forEach { emit(it) }
40 | return@flow
41 | }
42 | collect {
43 | mutableList.add(it)
44 | emit(it)
45 | }
46 | }
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src/main/kotlin/serialization/SerializationDemo.kt:
--------------------------------------------------------------------------------
1 | package serialization
2 |
3 | import kotlinx.serialization.SerialName
4 | import kotlinx.serialization.Serializable
5 | import kotlinx.serialization.decodeFromString
6 | import kotlinx.serialization.encodeToString
7 | import kotlinx.serialization.json.Json
8 |
9 | @Serializable
10 | data class ApiResponse(
11 | @Suppress("SpellCheckingInspection")
12 | val errcode: Int,
13 | val msg: String,
14 | val data: T,
15 | )
16 |
17 | @Serializable
18 | sealed class Section
19 |
20 | @Serializable
21 | @SerialName("shop")
22 | data class ShopSection(val name: String) : Section()
23 |
24 | @Serializable
25 | @SerialName("subject")
26 | data class SubjectSection(val id: Int) : Section()
27 |
28 | fun main() {
29 | val jsonString = """
30 | {"errcode":0,"msg":"ok","data":[{"type":"shop","name":"hello"},{"type":"subject","id":1}]}
31 | """.trimIndent()
32 | val result = Json.decodeFromString>>(jsonString)
33 |
34 | println(Json.encodeToString(result))
35 |
36 |
37 |
38 |
39 |
40 |
41 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/AsyncCrash.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.async
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 |
7 | suspend fun test(): Int {
8 | delay(1000)
9 | log("test")
10 | return 1
11 | // throw IllegalStateException("whoops in test")
12 | }
13 |
14 | suspend fun main() {
15 | // val result = GlobalScope.async { test() }
16 | //
17 | // result.await()
18 |
19 | val deferred = coroutineScope {
20 | async {
21 | test()
22 | }.also {
23 | log("in deferred end")
24 | }
25 | }
26 |
27 | val value = deferred.await()
28 |
29 | log("received $value")
30 |
31 |
32 | // try {
33 | // deferred.await()
34 | // } catch (e: Throwable) {
35 | // log("caught $e")
36 | // }
37 |
38 |
39 | // try {
40 | // val result = async { test() }
41 | // } catch (e: Throwable) {
42 | // log("caught $e")
43 | // }
44 |
45 | // delay(2000)
46 | // try {
47 | // result.await()
48 | // } catch (e: Throwable) {
49 | // log("caught $e")
50 | // }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/toy/FlowImplDemoWithoutReceiver.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow.toy
2 |
3 | import kotlinx.coroutines.delay
4 |
5 | typealias FlowCollector = suspend (value: T) -> Unit
6 |
7 | class FlowImpl2(private val builder: suspend (collector: FlowCollector) -> Unit) {
8 |
9 | suspend fun collect(collector: FlowCollector) = builder(collector)
10 |
11 | fun map(block: suspend (value: T) -> R) = FlowImpl2 { collector ->
12 | collect { value -> collector(block(value)) }
13 | }
14 |
15 | fun filter(block: suspend (value: T) -> Boolean) = FlowImpl2 { collector ->
16 | collect { value -> if (block(value)) collector(value) }
17 | }
18 | }
19 |
20 | suspend fun main() {
21 | FlowImpl2 { emit ->
22 | emit(1)
23 | emit(2)
24 | }
25 | .map {
26 | println("$it: in map")
27 | it * it
28 | }
29 | .filter {
30 | println("$it: in filter")
31 | println("$it: delaying in filter...")
32 | delay(3000)
33 | it % 2 == 0
34 | }
35 | .collect {
36 | println("$it: in collect")
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/fp/ArrowExceptionDemo.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("UNUSED_PARAMETER")
2 |
3 | package fp
4 |
5 | import arrow.*
6 | import arrow.core.*
7 | import arrow.core.computations.either
8 | import arrow.core.extensions.*
9 | import arrow.typeclasses.*
10 | import kotlin.random.Random
11 |
12 |
13 | sealed class ServiceException
14 | object NetworkUnstable : ServiceException()
15 | object WrongToken : ServiceException()
16 |
17 | fun getToken(): Either =
18 | if (Random.nextBoolean()) "token".right() else NetworkUnstable.left()
19 |
20 | fun uploadFile(token: String): Either =
21 | if (Random.nextBoolean()) WrongToken.left() else "success".right()
22 |
23 | fun sendMessage(messageId: String): Either = "success".right()
24 |
25 | suspend fun doWork() = either {
26 | val token = getToken().bind()
27 | val messageId = uploadFile(token).bind()
28 | return@either sendMessage(messageId).bind()
29 | }
30 |
31 | suspend fun main() {
32 | doWork().also {
33 | println(it)
34 | }
35 | }
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/jcip/MemoizerSuspendableDemo.kt:
--------------------------------------------------------------------------------
1 | package concurrency.jcip
2 |
3 | import kotlinx.coroutines.*
4 | import java.util.concurrent.ConcurrentHashMap
5 | import kotlin.time.ExperimentalTime
6 | import kotlin.time.TimeSource
7 |
8 | class SuspendableMemoizer(
9 | private val scope: CoroutineScope,
10 | private val computable: suspend (id: ID) -> V,
11 | ) {
12 | private val cache = ConcurrentHashMap>()
13 | suspend fun calculate(id: ID): V = cache.getOrPut(id) {
14 | scope.async(start = CoroutineStart.LAZY) {
15 | computable(id)
16 | }
17 | }.apply { start() }.await()
18 | }
19 |
20 | @OptIn(ExperimentalTime::class)
21 | suspend fun main() {
22 | val start = TimeSource.Monotonic.markNow()
23 |
24 | coroutineScope {
25 | val memoizer = SuspendableMemoizer(this) { id: Int ->
26 | println("computing id: $id")
27 | delay(id.toLong())
28 | }
29 | launch {
30 | memoizer.calculate(500)
31 | }
32 | launch {
33 | memoizer.calculate(500)
34 | }
35 | }
36 |
37 | println("elapsed: ${start.elapsedNow()}")
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/CaptureContextDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import kotlin.coroutines.CoroutineContext
4 | import kotlin.coroutines.coroutineContext
5 | import kotlin.coroutines.resume
6 | import kotlin.coroutines.suspendCoroutine
7 |
8 | suspend fun main() {
9 | println(checkCallerContext(coroutineContext)) // true
10 | println(checkContinuationContext()) // true
11 | }
12 |
13 | suspend fun checkCallerContext(callerContext: CoroutineContext): Boolean =
14 | // 不更新 context 的情况下和调用方的 context 相同
15 | callerContext === coroutineContext
16 |
17 | suspend fun checkContinuationContext(): Boolean {
18 | // suspendCoroutine 是连接 suspend 和回调的桥梁。
19 | // 传给它的 lambda 属于桥回调的那一边,不是 suspend 的 block,
20 | // 所以没有 coroutineContext。因此我们在桥的 suspend 这一边的时候
21 | // 保存一下这个 suspend 的 context
22 | val currentContext = coroutineContext
23 |
24 | // 通过 suspendCoroutine 获取当前 Continuation
25 | return suspendCoroutine { cont ->
26 | val contContext = cont.context
27 | // 两个 context 是相同的
28 | val isTheSame = contContext === currentContext
29 | cont.resume(isTheSame)
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/RaceDeferredDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.Deferred
4 | import kotlinx.coroutines.async
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.selects.select
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.TimeSource
10 |
11 | suspend fun data1(): Int {
12 | delay(500)
13 | return 1
14 | }
15 |
16 | suspend fun data2(): Int {
17 | delay(1000)
18 | return 2
19 | }
20 |
21 | /**
22 | * Race [Deferred] a la `Promise.race` in JavaScript.
23 | */
24 | // https://github.com/Kotlin/kotlinx.coroutines/issues/424
25 | @OptIn(ExperimentalTime::class)
26 | suspend fun main() {
27 | val start = TimeSource.Monotonic.markNow()
28 | coroutineScope {
29 | val deferred: List> = listOf(async { data1() }, async { data2() })
30 |
31 | val data = select {
32 | deferred.forEach { d -> d.onAwait { it } }
33 | }
34 |
35 | deferred.forEach { it.cancel() }
36 | println(data)
37 | }
38 |
39 | // A little more than 500ms.
40 | println("elapsed ${start.elapsedNow()}")
41 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/actor/ActorOverheadDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.actor
2 |
3 | import kotlinx.coroutines.ObsoleteCoroutinesApi
4 | import kotlinx.coroutines.channels.actor
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.runBlocking
7 | import kotlinx.coroutines.yield
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.measureTime
10 |
11 | val testSeq = (1..1000).asSequence()
12 |
13 | object ActorOverheadDemo {
14 | @ObsoleteCoroutinesApi
15 | suspend fun useActor() = coroutineScope {
16 | val actor = actor {
17 | val map = mutableSetOf()
18 | for (i in channel) map.add(i)
19 | }
20 | actor.offer(1)
21 | testSeq.forEach { actor.send(it) }
22 | actor.close()
23 | }
24 |
25 | suspend fun baseline() {
26 | val map = mutableSetOf()
27 | testSeq.forEach { map.add(it); yield() }
28 | }
29 | }
30 |
31 | @ObsoleteCoroutinesApi
32 | @ExperimentalTime
33 | fun main() = runBlocking {
34 | measureTime { ActorOverheadDemo.baseline() }.also { println(it) }
35 | measureTime { ActorOverheadDemo.useActor() }.also { println(it) }
36 | Unit
37 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/structuredconcurrency/StructuredJobDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost.structuredconcurrency
2 |
3 | import kotlinx.coroutines.*
4 |
5 | suspend fun main() = coroutineScope {
6 | val job =
7 | launch {
8 | launch {
9 | launch { delay(1000) }
10 | launch { delay(1000) }
11 | }
12 | launch {
13 | launch { delay(1000) }
14 | launch { delay(1000) }
15 | }
16 | }
17 | /**
18 | * After [Job] completes, child jobs are no longer visible in [Job.children].
19 | * So we [delay] a bit in order to observe the complete tree.
20 | *
21 | * I've also tried other alternatives:
22 | * * [yield] does not work.
23 | * * [launch] root with [Dispatchers.Unconfined] works.
24 | *
25 | * This example also shows that [Job.children] attribute
26 | * could be accessed concurrently.
27 | */
28 | delay(500)
29 |
30 | job.cancel()
31 |
32 | job.printAsTree()
33 | }
34 |
35 | fun Job.printAsTree(indent: Int = 0) {
36 | println("${" ".repeat(indent)}$this")
37 | children.forEach {
38 | it.printAsTree(indent + 2)
39 | }
40 | }
41 |
42 |
--------------------------------------------------------------------------------
/src/main/kotlin/fp/SyntaxDepInjectDemo.kt:
--------------------------------------------------------------------------------
1 | package fp
2 |
3 | class DslContext
4 | class HttpClient
5 |
6 | class Subject {
7 | var a: String = ""
8 | get() = "old"
9 | private set
10 |
11 | companion object {
12 | fun batchUpdate(subjects: List) {
13 | subjects.forEach {
14 | it.a = "new"
15 | }
16 | }
17 | }
18 | }
19 |
20 | class Poi
21 |
22 | interface FindSubjects {
23 | val context: DslContext
24 | fun findByIds(ids: List): List = TODO()
25 | }
26 |
27 | interface FindPoi {
28 | val client: HttpClient
29 | val context: DslContext
30 | fun findPoiById(id: String): Poi = TODO()
31 | }
32 |
33 | //---------------------- notice interface has multiple-inheritance
34 | interface LoadSubjectWithPoi : FindSubjects, FindPoi {
35 | fun load(ids: List) {
36 | val poi = findPoiById("hi")
37 | val subjects = findByIds(ids)
38 | // do stuff with poi and subjects
39 | }
40 | }
41 |
42 | fun main() {
43 | val loader = object : LoadSubjectWithPoi {
44 | override val context = DslContext()
45 | override val client = HttpClient()
46 | }
47 | loader.load(listOf(1, 2, 3))
48 | }
--------------------------------------------------------------------------------
/src/main/kotlin/serialization/MoshiDemo.kt:
--------------------------------------------------------------------------------
1 | package serialization
2 |
3 | import com.squareup.moshi.JsonClass
4 | import com.squareup.moshi.Moshi
5 | import kotlin.system.measureTimeMillis
6 |
7 | val moshi = Moshi.Builder().build()
8 |
9 | @JsonClass(generateAdapter = true)
10 | data class Post(val title: String, val body: String)
11 |
12 | fun main() {
13 | val a = moshi.adapter(Post::class.java).toJson(Post("foo", "bar"))
14 | .also { println(it) }
15 | //
16 | //
17 | // moshi.adapter(Post::class.java)
18 | // .lenient()
19 | // .fromJson("abc")
20 |
21 |
22 | measureTimeMillis {
23 | repeat(1000) {
24 | runCatching {
25 | moshi.adapter(Post::class.java)
26 | .lenient()
27 | .fromJson("""
28 | {"title":"foo","body":"bar"}
29 | """.trimIndent())
30 | }
31 | }
32 | }.let { println("result: $it") }
33 |
34 | measureTimeMillis {
35 | repeat(1000) {
36 | moshi.adapter(Post::class.java)
37 | .lenient()
38 | .fromJson("""
39 | {"title":"foo","body":"bar"}
40 | """.trimIndent())
41 | }
42 | }.let { println("result: $it") }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/kotlin/rutang/WeeklyActiveData.kt:
--------------------------------------------------------------------------------
1 | package rutang
2 |
3 | import java.time.DayOfWeek
4 | import java.time.LocalDate
5 | import java.time.Period
6 | import java.time.temporal.TemporalAdjuster
7 | import java.time.temporal.TemporalAdjusters
8 | import kotlin.time.days
9 |
10 | val mondays = sequence {
11 | var next = LocalDate.of(2020, 1, 1)
12 | val end = LocalDate.of(2020, 9, 1)
13 | while (true) {
14 | next = next.with(TemporalAdjusters.next(DayOfWeek.MONDAY))
15 | if (next > end) break
16 | yield(next)
17 | }
18 | }
19 |
20 | fun main() {
21 | val sqlStatements = mutableListOf()
22 | for (monday in mondays) {
23 | val next = monday + Period.ofDays(7)
24 | val sql = """
25 | select min(d), sum(r[1]), sum(r[2])
26 | from (
27 | select min(date) d, retention(toStartOfWeek(date, 1) = '$monday', toStartOfWeek(date, 1) = '$next') r
28 | from user_daily_api_records
29 | where toStartOfWeek(date, 1)>= '$monday' and toStartOfWeek(date , 1)<= '$next'
30 | and city_id = 107
31 | group by user_id )
32 | """.trimIndent()
33 | sqlStatements.add(sql)
34 | }
35 |
36 | println(sqlStatements.joinToString(" union all "))
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/QuickSelect2.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | fun smallestK2(arr: IntArray, k: Int): IntArray {
4 |
5 | fun swap(x: Int, y: Int) {
6 | val temp = arr[y]
7 | arr[y] = arr[x]
8 | arr[x] = temp
9 | }
10 |
11 | fun partition(lo: Int, hi: Int): Int {
12 | var i = lo - 1
13 | var j = hi + 1
14 | val pv = arr[lo]
15 |
16 | while (true) {
17 | do i++ while (arr[i] < pv)
18 | do j-- while (arr[j] > pv)
19 | if (j <= i) break
20 | swap(i, j)
21 | }
22 |
23 | swap(lo, j)
24 | return j
25 | }
26 |
27 |
28 | var lo = 0
29 | var hi = arr.lastIndex
30 |
31 | while (lo < hi) {
32 | val p = partition(lo, hi)
33 | if (p > k) {
34 | hi = p - 1
35 | } else if (p < k) {
36 | lo = p + 1
37 |
38 | } else break
39 |
40 | }
41 |
42 | val ret = IntArray(k)
43 |
44 | for (i in 0 until k) {
45 | ret[i] = arr[i]
46 | }
47 |
48 | return ret
49 | }
50 |
51 | fun main() {
52 | // val arr = intArrayOf(1, 3, 5, 7, 2, 4, 6, 8)
53 | // println(smallestK(arr, 4).toList())
54 |
55 | intArrayOf(1, 5, 2, 3, 4)
56 | .let { smallestK2(it, 4) }
57 | .also { println(it.toList()) }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/kotlin/fp/ReaderMonadDemo.kt:
--------------------------------------------------------------------------------
1 | package fp
2 |
3 | class ReaderMonadDemo {
4 | }
5 |
6 | class Reader(val run: (D) -> A) {
7 |
8 | inline fun map(crossinline fa: (A) -> B): Reader = Reader {
9 | d -> fa(run(d))
10 | }
11 |
12 | inline fun flatMap(crossinline fa: (A) -> Reader): Reader = Reader {
13 | d -> fa(run(d)).run(d)
14 | }
15 |
16 | companion object Factory {
17 | fun just(a: A): Reader = Reader { _ -> a }
18 |
19 | fun ask(): Reader = Reader { it }
20 | }
21 | }
22 |
23 | data class GetHeroesContext(
24 | val view: View,
25 | val getSuperHeroesUseCase: GetSuperHeroesUseCase,
26 | val heroesRepository: HeroesRepository,
27 | val dataSources: List
28 | )
29 |
30 | class GetSuperHeroesUseCase {
31 | // fun getSuperHeroes(): Reader> = Reader.ask().flatMap {
32 | // it.heroesRepository.getHeroes()
33 | // }
34 | }
35 | class HeroesRepository {
36 | fun getHeroes() = listOf(
37 | SuperHero("Superman"), SuperHero("Spider-Man")
38 | )
39 | }
40 | class HeroDataSource
41 | class View
42 |
43 | class SuperHero(val name: String)
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/ExceptionDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import java.lang.IllegalArgumentException
5 |
6 | suspend fun doStuff() {
7 | delay(500)
8 | throw IllegalStateException("whoops")
9 | }
10 |
11 | suspend fun test1() {
12 | supervisorScope {
13 | launch {
14 | doStuff()
15 | }
16 | }
17 | }
18 |
19 | fun someFuncAsync(block: () -> Unit) {
20 | block()
21 | }
22 |
23 | fun test3() {
24 | try {
25 | someFuncAsync {
26 | throw IllegalArgumentException("whoops")
27 | }
28 |
29 | } catch (e: Throwable) {
30 | println("caught $e")
31 | }
32 | }
33 |
34 | suspend fun test2() {
35 | coroutineScope {
36 | launch {
37 | delay(1000)
38 | throw IllegalArgumentException("whoops")
39 | }
40 |
41 | launch {
42 | delay(2000)
43 | println("hi")
44 | }
45 | }
46 | }
47 |
48 | suspend fun test5() {
49 | val scope = CoroutineScope(Job())
50 | val shared = SupervisorJob()
51 | scope.launch(shared) {
52 | throw IllegalArgumentException("whoops")
53 | }
54 | scope.launch {
55 | delay(1000)
56 | println("hi")
57 | }
58 | }
59 |
60 | suspend fun main() {
61 | coroutineScope {
62 | test2()
63 | }
64 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/StackToQueue.kt:
--------------------------------------------------------------------------------
1 | package algorithms
2 | import java.util.ArrayDeque
3 |
4 | class MyQueue() {
5 | val input = ArrayDeque()
6 | val output = ArrayDeque()
7 |
8 | /** Initialize your data structure here. */
9 |
10 | /** Push element x to the back of queue. */
11 | fun push(x: Int) {
12 | input.push(x)
13 | }
14 |
15 | /** Removes the element from in front of queue and returns that element. */
16 | fun pop(): Int {
17 | if (!output.isEmpty()) {
18 | return output.pop()
19 | }
20 | move()
21 | return output.pop()
22 | }
23 |
24 | /** Get the front element. */
25 | fun peek(): Int {
26 | move()
27 | return output.peek()
28 | }
29 |
30 | /** Returns whether the queue is empty. */
31 | fun empty(): Boolean {
32 | return output.isEmpty() && input.isEmpty()
33 | }
34 |
35 | private fun move() {
36 | while (!input.isEmpty()) {
37 | output.push(input.pop())
38 | }
39 | }
40 | }
41 |
42 | fun main() {
43 |
44 | // ["MyQueue","push","push","peek","push","peek"]
45 | // [[],[1],[2],[],[3],[]]
46 |
47 | val q = MyQueue()
48 | q.push(1)
49 | q.push(2)
50 | q.peek().also { println(it) }
51 | q.push(3)
52 | q.peek().also { println(it) }
53 |
54 | }
--------------------------------------------------------------------------------
/src/main/kotlin/tips/List.ws.kts:
--------------------------------------------------------------------------------
1 | import kotlin.random.Random
2 |
3 | val a = listOf(1, 2, 3)
4 | val b = listOf(2, 3, 4)
5 |
6 | println(a + b)
7 | println(a - b)
8 |
9 |
10 | List(5) { 0 }
11 |
12 |
13 | listOf(1, 2, 3).count { it % 2 == 0 }
14 |
15 | listOf(1, 2, 3, 4, 5).take(2)
16 |
17 | "Hello World!".take(5)
18 |
19 | data class Test(val a: String, val b: String)
20 |
21 | val t = Test("Hello", "World")
22 |
23 | val result = with(t) {
24 | when {
25 | a.isEmpty() -> 1
26 | else -> null
27 | }
28 | }
29 |
30 | listOf(1, 2, 3).any { it % 2 == 0 }
31 |
32 | listOf(1, 3).find { it % 2 == 0 }
33 |
34 |
35 | a.size.coerceAtLeast(10)
36 |
37 | class User
38 |
39 | fun toUserModel(value: String) = User()
40 |
41 | fun save(user: User) = Unit
42 | fun toast(msg: String) = Unit
43 |
44 | "Peter"
45 | .let(::toUserModel)
46 | .let(::save)
47 |
48 |
49 |
50 | fun getErrorMsg(): String? = if (Random.nextBoolean()) "whoops" else null
51 |
52 | fun doPublish() {
53 | val msg = getErrorMsg()
54 | if (msg != null) {
55 | toast(msg)
56 | return // I could forget to `return` here.
57 | }
58 | // do other stuff
59 | }
60 |
61 | "abcde".removePrefix("mn")
62 |
63 | buildString {
64 | append("hi")
65 | }
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/EndlessFlowDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.ConflatedBroadcastChannel
5 | import kotlinx.coroutines.channels.actor
6 | import kotlinx.coroutines.flow.asFlow
7 | import kotlinx.coroutines.flow.collect
8 | import kotlinx.coroutines.flow.emitAll
9 | import kotlinx.coroutines.flow.flow
10 |
11 | sealed class Message
12 |
13 | object Read : Message()
14 | class Write(val value: Int) : Message()
15 |
16 | @OptIn(ExperimentalCoroutinesApi::class)
17 | val dataChannel = ConflatedBroadcastChannel(0)
18 |
19 | @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class, ObsoleteCoroutinesApi::class)
20 | suspend fun main() {
21 |
22 | val f = flow {
23 | emitAll(dataChannel.asFlow())
24 | }
25 |
26 | coroutineScope {
27 | val actor = actor {
28 | for (msg in channel) {
29 | when (msg) {
30 | is Read -> Unit
31 | is Write -> {
32 | delay(500); dataChannel.send(msg.value)
33 | }
34 | }
35 | }
36 | }
37 | launch {
38 | delay(100)
39 | f.collect { println("collected $it") }
40 | }
41 |
42 | launch {
43 | delay(50)
44 | actor.send(Write(1))
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlowQuestion.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.ExperimentalCoroutinesApi
4 | import kotlinx.coroutines.async
5 | import kotlinx.coroutines.channels.produce
6 | import kotlinx.coroutines.coroutineScope
7 | import kotlinx.coroutines.delay
8 | import kotlinx.coroutines.flow.*
9 |
10 | @OptIn(ExperimentalCoroutinesApi::class)
11 | fun Flow.concurrent(
12 | concurrency: Int,
13 | transform: suspend (T) -> U,
14 | ): Flow = flow {
15 |
16 | coroutineScope {
17 | val channel = produce(capacity = concurrency) {
18 | collect { send(async { transform(it) }) }
19 | }
20 | for (el in channel) {
21 | emit(el.await())
22 | }
23 | }
24 | }
25 |
26 | suspend fun main() {
27 | val inputs = flow {
28 | println("will only print once")
29 | repeat(20) {
30 | emit(it)
31 | }
32 | }
33 | inputs // readInputs()
34 | .onEach {
35 | // extract...
36 | }
37 | .onEach {
38 | //
39 | }
40 | .transform {
41 | emit(it)
42 | }
43 | .transform {
44 | emit(it)
45 | emit(it)
46 | }
47 | .concurrent(5) {
48 | println("concurrently: $it")
49 | delay(1000)
50 | }
51 | .count() // or maintain in onEach
52 | .also { println("count: $it") }
53 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlowOverheadDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.ConflatedBroadcastChannel
5 | import kotlinx.coroutines.flow.asFlow
6 | import kotlinx.coroutines.flow.emitAll
7 | import kotlinx.coroutines.flow.first
8 | import kotlinx.coroutines.flow.flow
9 | import kotlin.time.ExperimentalTime
10 | import kotlin.time.measureTime
11 |
12 |
13 | @OptIn(ObsoleteCoroutinesApi::class, ExperimentalCoroutinesApi::class, FlowPreview::class)
14 | class FlowOverheadDemo(val scope: CoroutineScope) {
15 | val range = (1..1_000)
16 |
17 | val data: Map = range.associateBy { it }
18 | suspend fun baseline() {
19 | for (i in range) {
20 | data[i]; yield()
21 | }
22 | }
23 |
24 | val _dataChannel = ConflatedBroadcastChannel(0)
25 | val flow = flow {
26 | // emit(1)
27 | emitAll(_dataChannel.asFlow())
28 | }
29 |
30 | suspend fun useFlow() {
31 | for (i in range) {
32 | flow.first()
33 | }
34 | }
35 | }
36 |
37 | @OptIn(ExperimentalTime::class)
38 | suspend fun main() {
39 | coroutineScope {
40 | val demo = FlowOverheadDemo(this)
41 | measureTime { demo.baseline() }.also { println("baseline: $it") }
42 | measureTime { demo.useFlow() }.also { println("useFlow: $it") }
43 | }
44 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlowQ4.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.ExperimentalCoroutinesApi
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.*
6 | import kotlinx.coroutines.launch
7 |
8 | private object EndToken
9 |
10 | @Suppress("LocalVariableName")
11 | @OptIn(ExperimentalCoroutinesApi::class)
12 | fun Flow.concurrently(
13 | concurrency: Int = 10,
14 | block: suspend Flow.() -> Unit,
15 | ) = channelFlow {
16 | val _sharedFlow = MutableSharedFlow()
17 |
18 | @Suppress("UNCHECKED_CAST")
19 | val sharedFlow = _sharedFlow.takeWhile { it !is EndToken } as Flow
20 |
21 | launch { sharedFlow.block() }
22 | launch { sharedFlow.collect { send(it) } }
23 | delay(100)
24 | collect { _sharedFlow.emit(it as Any) }
25 | _sharedFlow.emit(EndToken)
26 | }
27 |
28 | suspend fun main() {
29 | flow { println("only once"); repeat(20) { emit(it + 1) } }
30 | .concurrently {
31 | delay(500)
32 | filter { it % 2 == 0 }.onEach { println("onEach $it") }.count().also { println("concurrent even: $it") }
33 | filter { it % 2 != 0 }.onEach { println("onEach $it") }.count().also { println("concurrent odd: $it") }
34 | }
35 | .collect {
36 | delay(200)
37 | println("collecting $it")
38 | }
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/QuickSelect.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort
2 |
3 | fun smallestK(arr: IntArray, k: Int): IntArray {
4 |
5 | fun swap(x: Int, y: Int) {
6 | val temp = arr[y]
7 | arr[y] = arr[x]
8 | arr[x] = temp
9 | }
10 |
11 | fun partition(lo: Int, hi: Int): Int {
12 | var i = lo + 1
13 | var j = hi
14 | val pv = arr[lo]
15 |
16 | while (true) {
17 | while (arr[i] < pv) {
18 | i++
19 | if (i == hi) break
20 | }
21 |
22 | while (arr[j] > pv) {
23 | j--
24 | if (j == 0) break
25 | }
26 |
27 | if (j <= i) break
28 | swap(i, j)
29 | }
30 |
31 | swap(lo, j)
32 | return j
33 | }
34 |
35 |
36 | var lo = 0
37 | var hi = arr.lastIndex
38 |
39 | while (lo < hi) {
40 | val p = partition(lo, hi)
41 | if (p > k) {
42 | hi = p - 1
43 | } else if (p < k) {
44 | lo = p + 1
45 |
46 | } else break
47 |
48 | }
49 |
50 | val ret = IntArray(k)
51 |
52 | for (i in 0 until k) {
53 | ret[i] = arr[i]
54 | }
55 |
56 | return ret
57 | }
58 |
59 | fun main() {
60 | // val arr = intArrayOf(1, 3, 5, 7, 2, 4, 6, 8)
61 | // println(smallestK(arr, 4).toList())
62 |
63 | intArrayOf(1, 5, 2, 3, 4)
64 | .let { smallestK(it, 4) }
65 | .also { println(it.toList()) }
66 |
67 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/CombineFlow.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.coroutineScope
5 | import kotlinx.coroutines.delay
6 | import kotlinx.coroutines.flow.*
7 | import kotlinx.coroutines.launch
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.seconds
10 |
11 | @ExperimentalTime
12 | suspend fun main() {
13 | suspend fun search(inputSearch: String, appliedSort: String): String {
14 | delay(1.seconds)
15 | return "search result for $inputSearch, sort: $appliedSort"
16 |
17 | }
18 |
19 | val inputSearch = MutableSharedFlow(replay = 1)
20 | val appliedSort = MutableSharedFlow(replay = 1)
21 |
22 | val searchResultFlow = combine(inputSearch, appliedSort) { search, sort ->
23 | search(search, sort)
24 | }
25 |
26 | coroutineScope {
27 | inputSearch.emit("q0")
28 | appliedSort.emit("0")
29 |
30 | log("launch 1")
31 | launch {
32 | delay(2.seconds); inputSearch.emit("q1")
33 | delay(2.seconds); inputSearch.emit("q2")
34 | }
35 |
36 | log("launch 2")
37 | launch {
38 | delay(6.seconds); appliedSort.emit("1")
39 | delay(2.seconds); appliedSort.emit("2")
40 | }
41 |
42 | log("launch 3")
43 | launch {
44 | searchResultFlow.collect { log("collected $it") }
45 | }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/main/kotlin/rx/RxDemo.kt:
--------------------------------------------------------------------------------
1 | package rx
2 |
3 | import io.reactivex.rxjava3.core.Flowable
4 | import io.reactivex.rxjava3.core.Observable
5 | import io.reactivex.rxjava3.core.Scheduler
6 | import io.reactivex.rxjava3.disposables.Disposable
7 | import io.reactivex.rxjava3.internal.schedulers.ExecutorScheduler
8 | import io.reactivex.rxjava3.internal.schedulers.NewThreadScheduler
9 | import io.reactivex.rxjava3.internal.schedulers.RxThreadFactory
10 | import io.reactivex.rxjava3.schedulers.Schedulers
11 |
12 | fun main() {
13 |
14 | val a: Disposable = Observable.just("hello world")
15 | .map { // 0
16 | println("[${Thread.currentThread().name}/map0]:$it")
17 | it.toUpperCase()
18 | }
19 | .subscribeOn(NewThreadScheduler(RxThreadFactory("demo")))
20 | .map { // 1
21 | println("[${Thread.currentThread().name}/map1]:$it")
22 | it.toUpperCase()
23 | }
24 | .observeOn(Schedulers.computation())
25 | .map { // 2
26 | println("[${Thread.currentThread().name}/map2]:$it")
27 | it.toUpperCase()
28 | }
29 | .observeOn(Schedulers.io())
30 | .map { // 3
31 | println("[${Thread.currentThread().name}/map3]:$it")
32 | it.toUpperCase()
33 | }
34 | .subscribe {
35 | println("[${Thread.currentThread().name}/subscribe]: $it")
36 | }
37 |
38 | while (true) {
39 |
40 | }
41 | }
42 |
43 |
--------------------------------------------------------------------------------
/src/main/kotlin/string/Quadratic.kt:
--------------------------------------------------------------------------------
1 | package string
2 |
3 | import kotlin.system.measureTimeMillis
4 |
5 | fun subText(value: String): String {
6 | var len = 0.0
7 | return value.codePoints().toArray().fold("") { acc, c ->
8 | println(acc)
9 | len += (if (c > 256) 1.0 else 0.5)
10 | if (len > 15) {
11 | return@fold acc
12 | }
13 | acc + c.toChar()
14 | }
15 | }
16 |
17 | fun subText2(value: String): String {
18 | var len = 0.0
19 |
20 | return buildString {
21 | value.codePoints().takeWhile {
22 | len += (if (it > 256) 1.0 else 0.5)
23 | len < 15
24 | }.forEach {
25 | println(it.toChar())
26 | append(it.toChar())
27 | }
28 | }
29 | }
30 |
31 | private val charPool: List = ('a'..'z') + ('A'..'Z') + ('0'..'9')
32 |
33 | fun randomString() = (1..10000)
34 | .map { i -> kotlin.random.Random.nextInt(0, charPool.size) }
35 | .map(charPool::get)
36 | .joinToString("");
37 |
38 |
39 | fun main() {
40 |
41 | subText(randomString())
42 |
43 | // val texts = (1..1000).map { randomString() }
44 | //
45 | // measureTimeMillis {
46 | // texts.map { subText2(it) }.let { println("result new is ${it.last()}") }
47 | // }.let { println("took $it") }
48 | //
49 | // measureTimeMillis {
50 | // texts.map { subText(it) }.let { println("result old is ${it.last()}") }
51 | // }.let { println("took $it") }
52 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FlowQ2.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import kotlinx.coroutines.FlowPreview
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.*
6 | import kotlinx.coroutines.flow.FlowCollector
7 | import kotlin.time.ExperimentalTime
8 | import kotlin.time.TimeSource
9 |
10 | @OptIn(FlowPreview::class)
11 | fun Flow.concurrentTransform(
12 | concurrency: Int,
13 | transform: suspend FlowCollector.(value: T) -> Unit,
14 | ): Flow = map {
15 | flow { transform(it) }
16 | }.flattenMerge(concurrency)
17 |
18 |
19 | suspend fun FlowCollector.second(i: Int) {
20 | delay((10 * i).toLong())
21 | emit(i * i)
22 | }
23 |
24 | @OptIn(ExperimentalTime::class)
25 | suspend fun main() {
26 | val sourceFlow = flow {
27 | println("only once")
28 | repeat(20) {
29 | emit(it)
30 | }
31 | }
32 |
33 | val now1 = TimeSource.Monotonic.markNow()
34 | var count1 = 0
35 | sourceFlow
36 | .transform { second(it) }
37 | .collect {
38 | count1++
39 | }
40 | println("counter1: $count1, took ${now1.elapsedNow()}")
41 |
42 |
43 | val now2 = TimeSource.Monotonic.markNow()
44 | var count2 = 0
45 | sourceFlow
46 | .concurrentTransform(5) {
47 | second(2)
48 | print(".")
49 | }
50 | .collect {
51 | count2++
52 | }
53 | println("counter2: $count2, took ${now2.elapsedNow()}")
54 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/3_LongestNonRepeatingSubstring.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("FunctionName")
2 |
3 | package algorithms.leetcode
4 |
5 | fun lengthOfLongestSubstring(s: String): Int {
6 | // [abc]abcbb
7 | // a[bca]bcbb
8 | // ab[cab]cbb
9 | // abc[abc]bb
10 | // abca[bcb]b
11 |
12 | // [abc]bbcbb
13 | // a[bcb]bcbb
14 | // ab[cbb]cbb
15 | // abc[bbc]bb
16 | // abcabcbb
17 |
18 | if (s.isEmpty()) return 0
19 | val set = mutableMapOf()
20 | var l = 0
21 | var r = 0
22 | set[s[0]] = 1
23 | while (r + 1 < s.length) {
24 | val next = s[r + 1]
25 | if (set[next]?: 0 > 0) {
26 | set[next] = set[next]!! - 1
27 | l++
28 | r++
29 | } else {
30 | set[next] = (set[next] ?: 0) + 1
31 | r++
32 | }
33 | }
34 | return r - l + 1
35 | }
36 |
37 | fun lengthOfLongestSubstring_nick(s: String): Int {
38 | var lo = 0
39 | var hi = 0
40 | var max = 0
41 | val set = hashSetOf()
42 | while (hi < s.length) {
43 | if (s[hi] in set) {
44 | set -= s[lo]
45 | lo++
46 | // hi++
47 | } else {
48 | set += s[hi]
49 | hi++
50 | max = Math.max(set.size, max)
51 | }
52 | }
53 |
54 | return max
55 | }
56 |
57 | fun main() {
58 | // println(lengthOfLongestSubstring("abcabcbb"))
59 |
60 | println(lengthOfLongestSubstring_nick("aab"))
61 | // [a]ab
62 | // [aa]b
63 | // [a]ab
64 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/quick/Quickselect.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort.quick
2 |
3 | fun quickSelect(arr: IntArray, k: Int, partition: (arr: IntArray, i: Int, j: Int) -> Int): Int {
4 | var lo = 0
5 | var hi = arr.lastIndex
6 | while (lo < hi) {
7 | val p = partition(arr, lo, hi)
8 | if (p < k) {
9 | // lo - p - k - hi
10 | lo = p + 1
11 | } else if (p > k) {
12 | // lo - k - p - hi
13 | hi = p - 1
14 |
15 | } else break
16 | }
17 | return arr[k]
18 | }
19 |
20 | fun quickSelectRange(arr: IntArray, k: Int, partition: (arr: IntArray, i: Int, j: Int) -> Int): List {
21 | var lo = 0
22 | var hi = arr.lastIndex
23 | while (lo < hi) {
24 | val p = partition(arr, lo, hi)
25 | if (p < k) {
26 | // lo - p - k - hi
27 | lo = p + 1
28 | } else if (p > k) {
29 | // lo - k - p - hi
30 | hi = p - 1
31 |
32 | } else break
33 | }
34 | return arr.slice(0..k)
35 | }
36 |
37 | fun main() {
38 | // quickSelect(intArrayOf(1, 5, 2, 3, 4), 3, ::myHoarePartition)
39 | // .also { println(it) }
40 | //
41 | // quickSelectRange(intArrayOf(1, 5, 2, 3, 4), 3, ::myHoarePartition)
42 | // .also { println(it) }
43 |
44 | quickSelectRange(intArrayOf(5, 5, 5, 5, 5), 3, ::myHoarePartition)
45 | .also { println(it) }
46 |
47 | quickSelect(intArrayOf(1, 4, 3, 2, 5), 2, ::doWhileHoarePartition)
48 | .also { println(it) }
49 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/ContinuationInterceptorDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.CoroutineName
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.runBlocking
6 | import kotlin.coroutines.*
7 |
8 | object ContinuationInterceptorDemo {
9 | suspend fun hello(): String {
10 | // delay(100)
11 | println("2. in suspend function")
12 | return "Hi"
13 | }
14 | }
15 |
16 | /**
17 | * ```
18 | * suspend fun main() {
19 | * println(hello())
20 | * }
21 | * ```
22 | */
23 | fun main() {
24 | ContinuationInterceptorDemo::hello.startCoroutine(Continuation(Printer) {
25 | println("4. result is $it")
26 | })
27 | }
28 |
29 | object Printer : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
30 | override fun interceptContinuation(continuation: Continuation): Continuation {
31 | val newCont = object : Continuation {
32 | override val context: CoroutineContext = continuation.context
33 |
34 | override fun resumeWith(result: Result) {
35 | println("resuming with $result")
36 | continuation.resumeWith(result)
37 | }
38 | }
39 | println("1. returning $newCont")
40 | return newCont
41 | }
42 |
43 | override fun releaseInterceptedContinuation(continuation: Continuation<*>) {
44 | super.releaseInterceptedContinuation(continuation)
45 | println("3. in release")
46 | }
47 | }
--------------------------------------------------------------------------------
/src/main/kotlin/cli/ObjectOrientedStyle.kt:
--------------------------------------------------------------------------------
1 | package cli
2 |
3 | import kotlinx.cli.*
4 | import kotlinx.cli.default
5 |
6 | abstract class CliCommand : HasParser, HasAfterJobHook {
7 | override val parser = ArgParser("")
8 |
9 | abstract fun run()
10 |
11 | private val jobs = mutableListOf<() -> Unit>()
12 |
13 | fun main(args: Array) {
14 | parser.parse(args)
15 | run()
16 | jobs.forEach { it() }
17 | }
18 |
19 | override fun addPostRunJob(job: () -> Unit) {
20 | jobs.add(job)
21 | }
22 | }
23 |
24 | interface ShouldSendFile : HasOutput, HasAfterJobHook {
25 | fun outputOption(): SingleOption {
26 | val shouldSend by parser.option(ArgType.Boolean, "send").default(false)
27 | val output = parser.option(ArgType.String).default("output.csv")
28 | addPostRunJob {
29 | if (shouldSend) {
30 | println("sending file to ${output.value}")
31 | }
32 | }
33 | return output
34 | }
35 | }
36 |
37 |
38 | interface HasParser {
39 | val parser: ArgParser
40 | }
41 |
42 |
43 | interface HasOutput : HasParser {
44 | val output: String
45 | }
46 |
47 | interface HasAfterJobHook {
48 | fun addPostRunJob(job: () -> Unit)
49 | }
50 |
51 | class MyJob : CliCommand(), ShouldSendFile {
52 | override val output by outputOption()
53 |
54 | override fun run() {
55 | println("writing to file $output")
56 | }
57 | }
58 |
59 | fun main(args: Array) = MyJob().main(args)
60 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/StateFlowCollect.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.GlobalScope
5 | import kotlinx.coroutines.coroutineScope
6 | import kotlinx.coroutines.delay
7 | import kotlinx.coroutines.flow.*
8 | import kotlinx.coroutines.launch
9 |
10 | suspend fun testSuspend(value: Int) {
11 | delay(1)
12 | }
13 |
14 | fun testNormal(value: Int) {
15 |
16 | }
17 |
18 | suspend fun hof() {
19 | }
20 |
21 |
22 | suspend fun main() {
23 |
24 | val a: suspend (value: Int) -> Unit = ::testSuspend
25 | // val b: suspend (value: Int) -> Unit = ::testNormal
26 |
27 | // val suspendingLambda: suspend () -> suspend (value: Int) -> Unit = suspend {
28 | // suspend { value -> Int
29 | // delay(1000)
30 | // }
31 | // }
32 |
33 |
34 | fun onReceiveFlow(state: StateFlow) {
35 | state.onEach {
36 | println("onEach $it")
37 | }.launchIn(GlobalScope)
38 | }
39 |
40 | val state = MutableStateFlow(0)
41 | onReceiveFlow(state)
42 |
43 | GlobalScope.launch {
44 | delay(1000)
45 | state.value += 1
46 |
47 | delay(1000)
48 | state.value += 1
49 |
50 | delay(1000)
51 | state.value += 1
52 | }
53 |
54 | while (true) {
55 | }
56 | // coroutineScope {
57 | // launch {
58 | // delay(1000)
59 | // state.value += 1
60 | //
61 | // delay(1000)
62 | // state.value += 1
63 | //
64 | // delay(1000)
65 | // state.value += 1
66 | // }
67 | // }
68 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/actor/DataStoreDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.actor
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.actor
5 |
6 |
7 | private sealed class Message {
8 | class Read(val key: String, val ack: CompletableDeferred) : Message()
9 | class Write(val key: String, val value: String, val ack: CompletableDeferred) : Message()
10 | }
11 |
12 | class SimpleDataStore(coroutineScope: CoroutineScope) {
13 |
14 | @OptIn(ObsoleteCoroutinesApi::class)
15 | private val actor = coroutineScope.actor { // this: ActorScope
16 | // state encapsulated inside the actor
17 | val cache = mutableMapOf()
18 |
19 | // looping over messages one by one
20 | for (msg in channel) {
21 | when (msg) {
22 | is Message.Read -> msg.ack.complete(cache[msg.key])
23 | is Message.Write -> {
24 | cache[msg.key] = msg.value;
25 | msg.ack.complete(Unit)
26 | }
27 | }
28 | }
29 | }
30 |
31 | suspend fun read(key: String): String? {
32 | val ack = CompletableDeferred()
33 | actor.send(Message.Read(key, ack))
34 | return ack.await()
35 | }
36 |
37 | suspend fun write(key: String, value: String) {
38 | val ack = CompletableDeferred()
39 | actor.send(Message.Write(key, value, ack))
40 | return ack.await()
41 | }
42 | }
43 |
44 | suspend fun main() {
45 | coroutineScope {
46 | val ds = SimpleDataStore(this + Job())
47 |
48 | ds.write("foo", "bar")
49 | println(ds.read("foo"))
50 | }
51 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/RemoveDuplicateNode.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | data class ListNode(
4 | val value: Int,
5 | var next: ListNode? = null
6 | ) : Iterable {
7 | fun toDebugString() = "[${joinToString()}]"
8 |
9 | override fun toString(): String {
10 | return value.toString()
11 | }
12 |
13 | override fun iterator(): Iterator {
14 | return object : Iterator {
15 | var next: ListNode? = this@ListNode
16 | override fun hasNext(): Boolean {
17 | return next != null
18 | }
19 |
20 | override fun next(): Int {
21 | return next!!.value.also {
22 | next = next?.next
23 | }
24 | }
25 | }
26 | }
27 | }
28 |
29 | fun listNodesOf(vararg num: Int): ListNode? {
30 | if (num.isEmpty()) return null
31 | val head = ListNode(num.first())
32 | var cur: ListNode? = head
33 | for (i in 1..num.lastIndex) {
34 | cur?.next = ListNode(num[i])
35 | cur = cur?.next
36 | }
37 | return head
38 | }
39 |
40 | fun removeDuplicateNodes(head: ListNode?): ListNode? {
41 | val set = hashSetOf()
42 |
43 | var prev: ListNode? = null
44 | var cur = head
45 |
46 | while (cur != null) {
47 | if (cur.value in set) {
48 | prev?.next = cur.next
49 | } else {
50 | set += cur.value
51 | }
52 | prev = cur
53 | cur = cur.next
54 | }
55 |
56 | return head
57 | }
58 |
59 | // [1, 2, 3, 3, 2, 1]
60 | fun main() {
61 | val head = listNodesOf(1, 2, 3, 3, 2, 1)
62 | removeDuplicateNodes(head).also { println(it?.toDebugString()) }
63 |
64 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/bank/optimistic/TransferMoneyTest.kt:
--------------------------------------------------------------------------------
1 | package concurrency.bank.optimistic
2 |
3 | import java.util.concurrent.*
4 | import kotlin.concurrent.thread
5 |
6 | fun main() {
7 | val transactions = TransactionRepository()
8 | val bank = BankService(transactions, Executors.newCachedThreadPool())
9 |
10 | val account1 = AccountImpl(1).apply { credit(100) }
11 | val account2 = AccountImpl(2).apply { credit(100) }
12 |
13 | // after tx1 - 1: 50, 2: 150
14 | // after tx2 - 1: 60, 2: 140
15 | val t1 = thread {
16 | bank.transfer(account1, account2, 50).getOrThrow()
17 | }
18 | val t2 = thread {
19 | bank.transfer(account2, account1, 10).getOrThrow()
20 | }
21 |
22 | t1.join()
23 | t2.join()
24 | println(account1)
25 | println(account2)
26 |
27 | val times = 1000
28 | val startGate = CountDownLatch(1)
29 | val endGate = CountDownLatch(times)
30 | val failedStats = ConcurrentHashMap()
31 |
32 | repeat(times) {
33 | thread {
34 | startGate.await()
35 | val r = ThreadLocalRandom.current()
36 | val from = if (r.nextBoolean()) account1 else account2
37 | val to = if (from == account1) account2 else account1
38 | bank.transfer(from, to, r.nextInt(10, 50)).getOrElse {
39 | failedStats.compute(it.toString()) { _, v: Int? -> (v ?: 0) + 1 }
40 | }
41 | endGate.countDown()
42 | }
43 | }
44 |
45 | startGate.countDown()
46 | endGate.await()
47 |
48 | println(account1)
49 | println(account2)
50 | require(account1.balance + account2.balance == 200)
51 | println("failed stats: $failedStats")
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/Contest.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | import java.util.HashSet
4 | import java.util.HashMap
5 |
6 |
7 | fun numDifferentIntegers(word: String): Int {
8 | if (word.length == 1) {
9 | return if (Character.isDigit(word[0])) 1 else 0
10 | }
11 | val set: MutableSet = LinkedHashSet()
12 | var prev = word[0]
13 | var n = 0
14 | if (Character.isDigit(prev)) n = prev.toInt()
15 | for (i in 1 until word.length) {
16 | val c = word[i]
17 | if (Character.isDigit(c)) {
18 | n = 10 * n + (c - '0')
19 | } else {
20 | if (Character.isDigit(prev)) {
21 | set.add(n)
22 | n = 0
23 | }
24 | }
25 | prev = c
26 | }
27 | if (n != 0) set.add(n)
28 | return set.size
29 | }
30 |
31 | fun evaluate(s: String, knowledge: List>): String? {
32 | val dict: MutableMap = HashMap()
33 | val sb = StringBuilder()
34 | for (k in knowledge) {
35 | dict[k[0]] = k[1]
36 | }
37 | var i = 0
38 | while (i < s.length) {
39 | val c = s[i]
40 | if (c == '(') {
41 | for ((k, v) in dict) {
42 | var match = true
43 | for (j in 0 until k.length) {
44 | if (k[j] != s[i + j + 1]) {
45 | match = false
46 | break
47 | }
48 | }
49 | if (match) {
50 | sb.append(v)
51 | i = k.length + 2
52 | }
53 | }
54 | } else {
55 | sb.append(c)
56 | i++
57 | }
58 | }
59 | return sb.toString()
60 | }
61 |
62 | fun main() {
63 | println(evaluate("(name)is(age)yearsold", listOf(listOf("name", "bob"), listOf("age", "two"))))
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/calculator/Expression.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.calculator
2 |
3 | import java.util.*
4 |
5 | sealed class Expression {
6 | abstract fun interpret(): Int
7 | }
8 |
9 | class Number(
10 | private val n: Int,
11 | ) : Expression() {
12 | override fun interpret() = n
13 | }
14 |
15 | class Plus(
16 | private val lhs: Expression,
17 | private val rhs: Expression,
18 | ) : Expression() {
19 | override fun interpret(): Int = lhs.interpret() + rhs.interpret()
20 | }
21 |
22 | class Minus(
23 | private val lhs: Expression,
24 | private val rhs: Expression,
25 | ) : Expression() {
26 | override fun interpret(): Int = lhs.interpret() - rhs.interpret()
27 | }
28 |
29 | class Multiply(
30 | private val lhs: Expression,
31 | private val rhs: Expression,
32 | ) : Expression() {
33 | override fun interpret(): Int = lhs.interpret() * rhs.interpret()
34 | }
35 |
36 | class Divide(
37 | private val lhs: Expression,
38 | private val rhs: Expression,
39 | ) : Expression() {
40 | override fun interpret(): Int = lhs.interpret() / rhs.interpret()
41 | }
42 |
43 | fun evalRPN(tokens: Array): Int {
44 | val operands = Stack()
45 | for (s in tokens) {
46 | val i = s.toIntOrNull()
47 | if (i != null) {
48 | operands.push(i)
49 | continue
50 | }
51 |
52 | with(operands) {
53 | when (s) {
54 | "+" -> push(pop() + pop())
55 | "-" -> push(pop().let { pop() - it })
56 | "*" -> push(pop() * pop())
57 | "/" -> push(pop().let { pop() / it })
58 | else -> TODO()
59 | }
60 | }
61 | }
62 | return operands.pop()
63 | }
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/SuspendingLambdaDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import org.litote.kmongo.fields
4 |
5 |
6 | val normalLambda: (value: Int) -> Int = { 1 }
7 |
8 | val normalHigherLambda: () -> (value: Int) -> Int = { { 1 } }
9 |
10 | //val suspendingLambda: suspend (value: Int) -> Int = suspend { v -> 1 }
11 |
12 | val suspendingLambdaNoArg: suspend () -> Int = suspend { 1 }
13 |
14 | val suspendingHigherLambdaNoArg: suspend () -> suspend () -> Unit = suspend { suspend { } }
15 |
16 | class Test(val p: Int) {
17 |
18 | }
19 |
20 | fun interface MyInterface {
21 | fun hi()
22 | }
23 |
24 | interface MyInterface2: MyInterface {
25 | fun bonjour()
26 | fun greeting()
27 | }
28 |
29 | class Test3 {
30 | var myInterface: MyInterface? = null
31 | set(value) {
32 | field = value
33 | }
34 |
35 | var myInterfaceJava: MyInterfaceJava? = null
36 | set(value) {
37 | field = value
38 | }
39 |
40 | fun setListener(value: MyInterfaceJava) {
41 |
42 | }
43 |
44 | fun setListenerKt(value: MyInterface) {
45 |
46 | }
47 | }
48 |
49 | fun main() {
50 |
51 | val t = Test(1)
52 | t.p
53 |
54 | val t2 = Test2()
55 | t2.p
56 |
57 | // var a: MyInterface se
58 |
59 | val t3 = Test3().apply {
60 | myInterface = object: MyInterface2 {
61 | override fun bonjour() {
62 | TODO("Not yet implemented")
63 | }
64 |
65 | override fun greeting() {
66 | TODO("Not yet implemented")
67 | }
68 |
69 | override fun hi() {
70 | TODO("Not yet implemented")
71 | }
72 |
73 | }
74 | }
75 |
76 | Test3().setListenerKt {
77 |
78 | }
79 |
80 | Test3().setListener {
81 |
82 | }
83 | }
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/blogpost/ArrowDemo.kt:
--------------------------------------------------------------------------------
1 | package coroutine.blogpost
2 |
3 | import arrow.core.Either
4 | import arrow.core.computations.either
5 | import arrow.core.flatMap
6 | import arrow.core.left
7 | import arrow.core.right
8 | import coroutine.blogpost.CookingException.*
9 | import kotlinx.coroutines.CoroutineScope
10 | import kotlinx.coroutines.coroutineScope
11 |
12 | sealed class CookingException {
13 | object LettuceIsRotten : CookingException()
14 | object KnifeNeedsSharpening : CookingException()
15 | data class InsufficientAmount(val quantityInGrams: Int) : CookingException()
16 | }
17 |
18 | object Lettuce; object Knife; object Salad
19 |
20 | fun takeFoodFromRefrigerator(): Either = Lettuce.right()
21 | fun getKnife(): Either = Knife.right()
22 | fun lunch(knife: Knife, food: Lettuce): Either = InsufficientAmount(5).left()
23 |
24 | fun getSalad(): Either =
25 | takeFoodFromRefrigerator()
26 | .flatMap { lettuce ->
27 | getKnife()
28 | .flatMap { knife ->
29 | val salad = lunch(knife, lettuce)
30 | salad
31 | }
32 | }
33 |
34 | suspend fun getSalad2() = either {
35 | val lettuce = takeFoodFromRefrigerator().bind()
36 | val knife = getKnife().bind()
37 | val salad = lunch(knife, lettuce).bind()
38 | salad
39 | }
40 |
41 | suspend fun main() {
42 | // CoroutineScope()
43 | val salad = either {
44 | val lettuce = takeFoodFromRefrigerator().bind()
45 | val knife = getKnife().bind()
46 | val salad = lunch(knife, lettuce).bind()
47 | salad
48 | }
49 | println(salad)
50 | }
51 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/calculator/BasicCalculator1.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.calculator
2 |
3 | import java.util.*
4 |
5 | fun calculate(s: String): Int {
6 | val exp: List = toRPN(s)
7 | val operands = Stack()
8 | with(operands) {
9 | for (c in exp) {
10 | if (c is Int) {
11 | push(c)
12 | continue
13 | }
14 | when (c) {
15 | '+' -> push(pop() + pop())
16 | '-' -> push(pop().let { pop() - it })
17 | '*' -> push(pop() * pop())
18 | '/' -> push(pop().let { pop() / it })
19 | }
20 | }
21 | }
22 | return operands.pop()
23 | }
24 |
25 | //val Char.weight get() = when(this) {
26 | // '+' -> 1
27 | // '-' -> 1
28 | // '(' -> 0
29 | // else -> TODO()
30 | //}
31 |
32 | fun toRPN(s: String): List {
33 | val ret = mutableListOf()
34 | val ops = Stack();
35 |
36 | var i = 0
37 | while (i < s.length) {
38 | val c = s[i]
39 | if (c.isDigit()) {
40 | var n = c - '0'
41 | while (++i < s.length && s[i].isDigit()) {
42 | n = 10 * n + (s[i] - '0')
43 | }
44 | ret += n
45 | continue
46 | }
47 |
48 | when {
49 | c == ' ' -> { }
50 | c == '(' -> ops.push(c)
51 | c == ')' -> {
52 | while (ops.peek() != '(') ret += ops.pop()
53 | ops.pop()
54 | }
55 | c.isDigit() -> ret += c
56 | else -> {
57 | while (!ops.isEmpty() && ops.peek().weight >= c.weight) {
58 | ret += ops.pop()
59 | }
60 | ops.push(c)
61 | }
62 | }
63 |
64 | i++
65 | }
66 | while (!ops.isEmpty()) ret += ops.pop()
67 | return ret
68 | }
69 |
70 | fun main() {
71 | calculate("2147483647").also { println(it) }
72 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/jcip/AqsValueLatch.kt:
--------------------------------------------------------------------------------
1 | package concurrency.jcip
2 |
3 | import java.util.concurrent.FutureTask
4 | import java.util.concurrent.locks.AbstractQueuedSynchronizer
5 | import kotlin.concurrent.thread
6 |
7 | /**
8 | * Reference
9 | * - JCIP, p.184
10 | * - FutureTask before jdk8 https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/concurrent/FutureTask.java
11 | */
12 | class ValueLatch {
13 | private class Sync : AbstractQueuedSynchronizer() {
14 | private var result: T? = null
15 |
16 | override fun tryAcquireShared(arg: Int): Int {
17 | return if (state == 1) 1 else -1
18 | }
19 |
20 | override fun tryReleaseShared(arg: Int): Boolean {
21 | state = 1
22 | return true
23 | }
24 |
25 | fun innerGet(): T {
26 | acquireSharedInterruptibly(0)
27 | return result!!
28 | }
29 |
30 | fun innerSet(value: T) {
31 | result = value
32 | while (true) {
33 | if (state == 1) return
34 | if (compareAndSetState(0, 1)) {
35 | releaseShared(0)
36 | result = value
37 | }
38 | }
39 | }
40 |
41 | fun isSet(): Boolean {
42 | return state == 1
43 | }
44 | }
45 |
46 | private val sync = Sync()
47 |
48 | fun isSet(): Boolean {
49 | return sync.isSet()
50 | }
51 |
52 | fun setValue(value: T) {
53 | sync.innerSet(value)
54 | }
55 |
56 | fun getValue(): T {
57 | return sync.innerGet()
58 | }
59 | }
60 |
61 | fun main() {
62 | val latch = ValueLatch()
63 |
64 | thread {
65 | Thread.sleep(500)
66 | latch.setValue(10)
67 | }
68 |
69 | repeat(10) {
70 | thread {
71 | println("value is ${latch.getValue()}")
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/src/main/kotlin/dataloader/DataloaderDemo.kt:
--------------------------------------------------------------------------------
1 | package dataloader
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.Channel
5 | import kotlinx.coroutines.flow.MutableStateFlow
6 | import java.util.concurrent.ConcurrentHashMap
7 |
8 | //interface BatchLoader {
9 | // suspend fun load(ids: List)
10 | //}
11 |
12 | class BatchLoader(
13 | block: suspend (id: List) -> List,
14 | ) {
15 | suspend fun CoroutineScope.load(id: ID): T {
16 | TODO()
17 |
18 | }
19 | }
20 |
21 | data class User(val id: Int, val invitedBy: Int)
22 |
23 | class BatchLoader2(
24 | val scope: CoroutineScope,
25 | val block: suspend (id: List) -> List,
26 | ) {
27 | private val cache = ConcurrentHashMap()
28 |
29 | private val ids = mutableSetOf()
30 |
31 | private val ids2Index = mutableMapOf()
32 |
33 | private val result = Channel>()
34 |
35 |
36 | @Synchronized
37 | fun load(id: ID): Deferred {
38 | ids2Index[id] = ids.size
39 | ids.add(id)
40 |
41 | return scope.async {
42 | val items = result.receive()
43 | val index = checkNotNull(ids2Index[id])
44 | items[index]
45 | }
46 | }
47 |
48 | suspend fun dispatchAndJoin() {
49 | result.send(block(ids.toList()))
50 | result.close()
51 | }
52 | }
53 |
54 | suspend fun main() {
55 | // val loader = BatchLoader {
56 | // delay(1000)
57 | // listOf(User(1, 3), User(2, 4))
58 | // }
59 |
60 | coroutineScope {
61 | val loader = BatchLoader2(this) {
62 | delay(1000)
63 | listOf(User(1, 3), User(2, 4))
64 | }
65 |
66 | loader.load(1).also { println(it.await()) }
67 | loader.load(2).also { println(it.await()) }
68 | loader.dispatchAndJoin()
69 | }
70 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/calculator/ShuntingYard.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode.calculator
2 |
3 | import java.lang.StringBuilder
4 | import java.util.*
5 |
6 |
7 | val Char.weight
8 | get() = when (this) {
9 | '+' -> 1
10 | '-' -> 1
11 | '*' -> 2
12 | '/' -> 2
13 | '(' -> 0
14 | else -> TODO("unrecognized [$this]")
15 | }
16 |
17 | fun shuntingYard(string: String): String {
18 | val ret = StringBuilder()
19 | val operators = Stack()
20 |
21 | for (c in string.toCharArray()) {
22 | if (Character.isLetter(c)) {
23 | ret.append(c)
24 | } else {
25 | while (
26 | !operators.isEmpty()
27 | && operators.peek().weight >= c.weight
28 | ) ret.append(operators.pop())
29 |
30 | operators.push(c)
31 | }
32 | }
33 |
34 | while (!operators.isEmpty()) ret.append(operators.pop())
35 |
36 | return ret.toString()
37 | }
38 |
39 | fun shuntingYardWithBrackets(string: String): String {
40 | val ret = StringBuilder()
41 | val ops = Stack()
42 |
43 | for (c in string.toCharArray()) {
44 | when {
45 | Character.isLetter(c) -> ret.append(c)
46 | c == '(' -> ops.push(c)
47 | c == ')' -> {
48 | while (ops.peek() != '(') ret.append(ops.pop())
49 | ops.pop()
50 | }
51 | else -> {
52 | while (!ops.isEmpty() && ops.peek().weight >= c.weight) {
53 | ret.append(ops.pop())
54 | }
55 | ops.push(c)
56 | }
57 | }
58 | }
59 |
60 | while (!ops.isEmpty()) ret.append(ops.pop())
61 |
62 | return ret.toString()
63 | }
64 |
65 | fun main() {
66 | shuntingYard("a+b*c-d").also { println(it) } // 123*+4-
67 | shuntingYardWithBrackets("a+(b+c)+d").also { println(it) }
68 | shuntingYardWithBrackets("a+(m+n*o-p)+d").also { println(it) }
69 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/RetriableCoroutine.kt:
--------------------------------------------------------------------------------
1 | package coroutine
2 |
3 | import kotlinx.coroutines.*
4 | import kotlinx.coroutines.channels.Channel
5 | import java.util.concurrent.atomic.AtomicInteger
6 | import kotlin.random.Random
7 | import kotlin.time.ExperimentalTime
8 | import kotlin.time.seconds
9 |
10 | suspend fun fetchCredential(): String {
11 | delay(1000)
12 | return "xxx-xxx-xxx"
13 | }
14 |
15 | suspend fun uploadImage(token: String, imageId: Int): String {
16 | log("starting to upload image $imageId with token $token")
17 | delay(1000)
18 | if (Random.nextBoolean()) throw RuntimeException("whoops, image $imageId failed")
19 | return "https://example.com/$imageId"
20 | }
21 |
22 |
23 | val retryRequest = Channel()
24 |
25 | val failedCount = AtomicInteger(0)
26 |
27 | suspend fun attempt(block: suspend () -> T): T {
28 | while (true) {
29 | try {
30 | return block()
31 | } catch (e: Throwable) {
32 | log("caught exception $e")
33 | failedCount.incrementAndGet()
34 | retryRequest.receive()
35 | }
36 | }
37 | }
38 |
39 | @ExperimentalTime
40 | suspend fun main() {
41 | val imagesToUpload = (1..5)
42 |
43 | // simulate user clicking retry button
44 | GlobalScope.launch {
45 | while (true) {
46 | delay(5.seconds)
47 | log("sending retry request")
48 | repeat(failedCount.getAndSet(0)) { retryRequest.send(Unit) }
49 | }
50 | }
51 |
52 | coroutineScope {
53 | val token = attempt {
54 | fetchCredential().also { log("fetched token $it") }
55 | }
56 |
57 | // val urls = imagesToUpload.map {
58 | // attempt { uploadImage(token, it) }
59 | // }
60 |
61 | val futures = imagesToUpload.map {
62 | async { attempt { uploadImage(token, it) } }
63 | }
64 |
65 | val urls = futures.map { it.await() }
66 | log("finished uploading $urls")
67 | }
68 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FrpState.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("DuplicatedCode")
2 |
3 | package coroutine.flow
4 |
5 | import coroutine.log
6 | import kotlinx.coroutines.*
7 | import kotlinx.coroutines.flow.*
8 |
9 | @FlowPreview
10 | @ExperimentalCoroutinesApi
11 | suspend fun main() {
12 |
13 | fun Flow.handleLike(state: UiState): Flow = transform {
14 | emit(state.apply { loading = true })
15 | log("call like api, position: ${it.position}")
16 | delay(500)
17 | emit(state.apply { likedPosition = it.position; loading = false })
18 | }
19 |
20 | fun Flow.handleSearch(state: UiState): Flow = transform {
21 | emit(state.apply { loading = true })
22 | log("call search api, query: ${it.value}")
23 | delay(200)
24 | emit(state.apply { query = it.value; loading = false })
25 | }
26 |
27 | val refresh = MutableSharedFlow()
28 | val like = MutableSharedFlow()
29 | val search = MutableSharedFlow()
30 |
31 | coroutineScope {
32 | val actions: Flow = merge(refresh, like, search)
33 |
34 | launch { // simulate user actions
35 | delay(500); like.emit(UiAction.LikeArticle(1))
36 | delay(500); search.emit(UiAction.SearchQuery("foo"))
37 | delay(500); like.emit(UiAction.LikeArticle(2))
38 | delay(500); search.emit(UiAction.SearchQuery("bar"))
39 | }
40 |
41 | val state: Flow = flow {
42 | var last = UiState().also { emit(it) }
43 |
44 | val merged = merge(
45 | actions.filterIsInstance().handleSearch(last),
46 | actions.filterIsInstance().handleLike(last)
47 | ).onEach { last = it }
48 |
49 | emitAll(merged)
50 | }
51 |
52 | state.collect {
53 | log("💡----------------------------$it")
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/bank/optimistic/SimNetworkErrorTest.kt:
--------------------------------------------------------------------------------
1 | package concurrency.bank.optimistic
2 |
3 | import java.util.concurrent.*
4 | import kotlin.concurrent.thread
5 |
6 | private fun observe(
7 | account1: Account,
8 | account2: Account,
9 | transactions: TransactionRepository
10 | ) {
11 | println("account1: ${account1.balance}, account2: ${account2.balance}")
12 |
13 | val remaining = transactions.asSequence()
14 | .filter { it.status == Transaction.Status.DebitSuccess }
15 | .sumOf { it.amount }
16 | .also { println("remaining $it") }
17 |
18 | val total = account1.balance + account2.balance + remaining == 200
19 | val count = transactions.count { it.status == Transaction.Status.TxSuccess }
20 | println("total money: $total, success count $count")
21 | }
22 |
23 | fun main() {
24 | val executor = Executors.newCachedThreadPool()
25 | val transactions = TransactionRepository()
26 | val bank = BankService(transactions, executor)
27 |
28 | val account1 = RemoteAccount(1).apply { credit(100) }
29 | val account2 = RemoteAccount(2).apply { credit(100) }
30 |
31 | val times = 1000
32 | val startGate = CountDownLatch(1)
33 | val endGate = CountDownLatch(times)
34 | val failedStats = ConcurrentHashMap()
35 |
36 | repeat(times) {
37 | thread {
38 | startGate.await()
39 | val r = ThreadLocalRandom.current()
40 | val from = if (r.nextBoolean()) account1 else account2
41 | val to = if (from == account1) account2 else account1
42 | bank.transfer(from, to, r.nextInt(10, 50)).getOrElse {
43 | failedStats.compute(it.toString()) { _, v: Int? -> (v ?: 0) + 1 }
44 | }
45 | endGate.countDown()
46 | }
47 | }
48 |
49 | startGate.countDown()
50 |
51 | thread {
52 | Thread.sleep(50)
53 | account2.disconnect()
54 | Thread.sleep(70)
55 | account2.reconnect()
56 | }
57 |
58 |
59 | endGate.await()
60 |
61 | observe(account1, account2, transactions)
62 | println("failed stats: $failedStats")
63 |
64 | executor.shutdown()
65 | executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)
66 | observe(account1, account2, transactions)
67 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/sort/quick/Quicksort.kt:
--------------------------------------------------------------------------------
1 | package algorithms.sort.quick
2 |
3 | fun swap(arr: IntArray, i: Int, j: Int) {
4 | val temp = arr[j]
5 | arr[j] = arr[i]
6 | arr[i] = temp
7 | }
8 |
9 | fun myHoarePartition(arr: IntArray, lo: Int, hi: Int): Int {
10 | val pv = arr[lo]
11 | var i = lo + 1
12 | var j = hi
13 | while (true) {
14 | while (arr[i] < pv) {
15 | i++
16 | if (i == hi) break
17 | }
18 | while (arr[j] > pv) {
19 | j--
20 | if (j == lo) break
21 | }
22 | if (j <= i) break
23 | swap(arr, i, j)
24 | }
25 |
26 | swap(arr, lo, j)
27 | return j
28 | }
29 |
30 | fun doWhileHoarePartition(arr: IntArray, lo: Int, hi: Int): Int {
31 | var i = lo
32 | var j = hi + 1
33 | val pv = arr[lo]
34 | while (true) {
35 | do i++ while (i <= hi && arr[i] < pv)
36 | do j-- while (j >= lo && arr[j] > pv)
37 | if (j < i) break
38 | swap(arr, i, j)
39 | }
40 | swap(arr, lo, j)
41 | return j
42 | }
43 |
44 | fun quickSort(
45 | arr: IntArray,
46 | partition: (arr: IntArray, lo: Int, hi: Int) -> Int
47 | ) {
48 | fun sort(lo: Int, hi: Int) {
49 | if (lo < hi) {
50 | val p = partition(arr, lo, hi)
51 | sort(lo, p - 1)
52 | sort(p + 1, hi)
53 | }
54 | }
55 | sort(0, arr.lastIndex)
56 | }
57 |
58 | fun quickSort(partition: (arr: IntArray, lo: Int, hi: Int) -> Int): (IntArray) -> Unit {
59 | return { arr: IntArray -> quickSort(arr, partition) }
60 | }
61 |
62 | fun main() {
63 | // intArrayOf(1, 5, 2, 3, 4)
64 | // .apply { quickSort(::myHoarePartition)(this) }
65 | // .also { println(it.toList()) }
66 | //
67 | // intArrayOf(1, 5, 5, 3, 4)
68 | // .apply { quickSort(::myHoarePartition)(this) }
69 | // .also { println(it.toList()) }
70 |
71 | intArrayOf(1, 5, 2, 3, 4)
72 | .apply { quickSort(::doWhileHoarePartition)(this) }
73 | .also { println(it.toList()) }
74 |
75 | intArrayOf(3, 3, 3, 3, 3)
76 | .apply { quickSort(::doWhileHoarePartition)(this) }
77 | .also { println(it.toList()) }
78 |
79 | // stuck...
80 | intArrayOf(3, 3, 3, 3, 3)
81 | .apply { quickSort(::myHoarePartition)(this) }
82 | .also { println(it.toList()) }
83 | }
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/LRUCache.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | class LRUCache(val capacity: Int) {
4 | private val map = mutableMapOf()
5 | private val head = Node(null, null, 0, 0)
6 | private val tail = Node(null, null, 0, 0)
7 |
8 | init {
9 | head.next = tail
10 | tail.prev = head
11 | }
12 |
13 | fun get(key: Int): Int {
14 | val node = map[key] ?: return -1
15 | remove(node)
16 | insertToHead(node)
17 | return node.value
18 | }
19 |
20 | fun put(key: Int, value: Int) {
21 | if (key in map) {
22 | val node = map[key]!!
23 | node.value = value
24 | remove(node)
25 | node.insertAfter(head)
26 | return
27 | }
28 | val node = Node(null, null, key, value)
29 | map[key] = node
30 | node.insertAfter(head)
31 | if (map.size > capacity) {
32 | map.remove(removeTail().key)
33 | }
34 | }
35 |
36 | private fun removeTail(): Node {
37 | val removing = tail.prev!!
38 | remove(removing)
39 | return removing
40 | }
41 |
42 | private fun remove(node: Node) {
43 | node.prev?.next = node.next
44 | node.next?.prev = node.prev
45 | }
46 |
47 | // node -> this
48 | private fun Node.insertAfter(node: Node) {
49 | val last = node.next
50 | node.next = this
51 | this.prev = node
52 | this.next = last
53 | last?.prev = this
54 | }
55 |
56 |
57 | private fun insertToHead(node: Node) {
58 | val replacing = head.next!!
59 | replacing.prev = node
60 | node.prev = head
61 | node.next = replacing
62 | head.next = node
63 | }
64 |
65 | private class Node(
66 | var prev: Node?,
67 | var next: Node?,
68 | val key: Int,
69 | var value: Int
70 | ) {
71 | override fun toString() = key.toString()
72 | }
73 | }
74 |
75 | fun main() {
76 |
77 | with(LRUCache(2)) {
78 | put(2, 1)
79 | put(1, 1)
80 | put(2, 3)
81 | put(4, 1)
82 | get(1).also { println(it) } // -1
83 | get(2).also { println(it) }
84 | }
85 | //
86 | // with(LRUCache(2)) {
87 | // put(1, 1)
88 | // put(2, 2)
89 | // get(1)
90 | // put(3, 3)
91 | // get(2).also { println(it) }
92 | // put(4, 4)
93 | // get(1)
94 | // get(3)
95 | // get(4)
96 | // }
97 |
98 | }
--------------------------------------------------------------------------------
/src/main/kotlin/concurrency/bank/twopc/BankServiceImpl.kt:
--------------------------------------------------------------------------------
1 | package concurrency.bank.twopc
2 |
3 | import concurrency.bank.twopc.Transaction.State.*
4 | import java.util.concurrent.Executor
5 | import java.util.concurrent.atomic.AtomicInteger
6 |
7 | class AccountImpl(
8 | override val id: Int
9 | ) : Account {
10 | private val _balance = AtomicInteger()
11 | override val balance: Int get() = _balance.get()
12 | private val pending = mutableSetOf()
13 |
14 | override fun credit(amount: Int) {
15 | _balance.getAndUpdate { it + amount }
16 | }
17 |
18 | override fun debit(amount: Int) {
19 | _balance.getAndUpdate { it - amount }
20 | }
21 |
22 | override fun apply(id: Int, amount: Int) {
23 | synchronized(this) {
24 | if (id in pending) return
25 | _balance.getAndUpdate { it + amount }
26 | pending += id
27 | }
28 | }
29 |
30 | override fun commit(id: Int) {
31 | pending -= id
32 | }
33 | }
34 |
35 | class BankServiceImpl(
36 | private val executor: Executor
37 | ) : BankService {
38 | private val nextTxId = AtomicInteger(0)
39 | private val transactions = mutableMapOf()
40 |
41 | private fun save(tx: Transaction) {
42 | transactions[tx.id] = tx
43 | }
44 |
45 | private fun process(tx: Transaction): Transaction {
46 | val from = tx.from
47 | val to = tx.to
48 | return when (tx.state) {
49 | Initial -> process(
50 | tx.copy(state = Pending).also { save(it) }
51 | )
52 | Pending -> {
53 | from.apply(tx.id, -tx.amount)
54 | to.apply(tx.id, tx.amount)
55 | process(tx.copy(state = Applied).also { save(it) })
56 | }
57 | Applied -> {
58 | from.commit(tx.id)
59 | to.commit(tx.id)
60 | process(tx.copy(state = Done).also { save(it) })
61 | }
62 | Done -> tx
63 | }
64 | }
65 |
66 | override fun transfer(from: Account, to: Account, amount: Int): Result {
67 | val tx = Transaction(nextTxId.getAndIncrement(), from, to, amount, Initial)
68 | return runCatching {
69 | process(tx)
70 | }.onFailure {
71 | executor.execute {
72 | var tx = tx
73 | while (tx.state != Done) {
74 | tx = process(tx)
75 | }
76 | }
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
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 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/kotlin/rx/ComparisonWithSequenceDemo.kt:
--------------------------------------------------------------------------------
1 | package rx.comparison
2 |
3 | import io.reactivex.rxjava3.core.Observable
4 | import kotlinx.coroutines.delay
5 | import kotlinx.coroutines.flow.*
6 | import kotlinx.coroutines.runBlocking
7 | import java.util.concurrent.Phaser
8 | import kotlin.time.ExperimentalTime
9 | import kotlin.time.seconds
10 |
11 | @ExperimentalTime
12 | suspend fun uploadImage(url: String): String {
13 | delay(1.seconds); println(url)
14 | return "url"
15 | }
16 |
17 | @ExperimentalTime
18 | fun withCoroutine() {
19 | sequenceOf("image-1", "image-2", "image-3")
20 | .map {
21 | return@map runBlocking { uploadImage(it) }
22 | }
23 | .filter {
24 | it.startsWith("abc")
25 | }
26 | }
27 |
28 | fun withAsyncCallback() {
29 | fun uploadImageAsync(url: String, onSuccess: (url: String) -> Unit) {
30 | val thread = Thread {
31 | Thread.sleep(1000)
32 | }
33 | thread.start()
34 | thread.join()
35 | onSuccess(url)
36 | }
37 |
38 | sequenceOf("image-1", "image-2", "image-3")
39 | .map {
40 | uploadImageAsync(it) {
41 | // ???
42 | }
43 | }
44 | // .filter
45 | }
46 |
47 | fun withJdkConcurrencyControl() {
48 | fun uploadImageAsync(url: String, onSuccess: (url: String) -> Unit) {
49 | val thread = Thread {
50 | Thread.sleep(2000)
51 | }
52 | thread.start()
53 | thread.join()
54 | onSuccess("http://$url")
55 | }
56 |
57 | val phaser = Phaser(0)
58 | sequenceOf("image-1", "image-2", "image-3")
59 | .onEach {
60 | phaser.register()
61 | }
62 | .map {
63 | println("starting to upload $it")
64 | var url: String? = null
65 | uploadImageAsync(it) {
66 | println("received $it")
67 | phaser.arriveAndDeregister()
68 | url = it
69 | }
70 | return@map url!!
71 | }
72 | .filter {
73 | it.endsWith("1")
74 | }
75 | .forEach {
76 | println("Got it $it")
77 | }
78 | }
79 |
80 | fun withRxJava() {
81 | fun uploadImage(image: String): Observable = Observable.just("http://$image")
82 |
83 | Observable.just("image-1", "image-2", "image-3")
84 | .flatMap {
85 | uploadImage(it)
86 | }
87 | .filter {
88 | it.endsWith("1")
89 | }
90 | .subscribe {
91 | println(it)
92 | }
93 | }
94 |
95 |
96 | @ExperimentalTime
97 | suspend fun withFlow() {
98 | flowOf("image-1", "image-2", "image-3")
99 | .map {
100 | uploadImage(it)
101 | }
102 | .filter { it.endsWith("1") }
103 | .collectLatest {
104 | println(it)
105 | }
106 | }
107 |
108 |
109 | @ExperimentalTime
110 | fun main() {
111 | println("------------------------")
112 | withJdkConcurrencyControl()
113 |
114 | flow {
115 | emit(1)
116 | }
117 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/continuation/ManualContinuationExercise.kt:
--------------------------------------------------------------------------------
1 | package coroutine.continuation
2 |
3 | import kotlinx.coroutines.delay
4 | import java.util.concurrent.CountDownLatch
5 | import kotlin.coroutines.Continuation
6 | import kotlin.coroutines.CoroutineContext
7 | import kotlin.coroutines.EmptyCoroutineContext
8 | import kotlin.coroutines.resume
9 | import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
10 | import kotlin.time.ExperimentalTime
11 | import kotlin.time.TimeSource
12 |
13 |
14 | /**
15 | * At compile time, Kotlin generates state-machine code for each suspend function.
16 | *
17 | * This exercise simulates the following suspend function.
18 | *
19 | * ```kotlin
20 | * suspend fun foo() {
21 | * delay(1000)
22 | * return 1
23 | * }
24 | *
25 | * suspend fun main() {
26 | * println(foo())
27 | * }
28 | * ```
29 | */
30 | @ExperimentalTime
31 | fun main() {
32 | // Use a latch to keep the JVM spinning.
33 | val latch = CountDownLatch(1)
34 | // Record the elapsed time.
35 | val timer = TimeSource.Monotonic.markNow()
36 |
37 | foo(object : Continuation {
38 | // CoroutineContext is irrelevant in this example.
39 | override val context: CoroutineContext = EmptyCoroutineContext
40 |
41 | override fun resumeWith(result: Result) {
42 | println(result.getOrThrow())
43 | latch.countDown()
44 | }
45 | })
46 |
47 | latch.await()
48 | println("elapsed: ${timer.elapsedNow()}")
49 | }
50 |
51 | fun foo(continuation: Continuation): Any {
52 | // In effect, state machines sub-classes kotlin.coroutines.jvm.internal.ContinuationImpl.
53 | class FooContinuation : Continuation {
54 | var label: Int = 0
55 |
56 | // See kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith.
57 | // Source code does recursion unrolling, which complicates the code a bit.
58 | // Relevant commit: https://github.com/jetbrains/kotlin/commit/822faca75a14d27026f2f1034ac9a99976318f22
59 | // Note that the pre-optimization code in the above link is much easier to read.
60 | // Relevant issue: https://youtrack.jetbrains.com/issue/KT-18987
61 | override fun resumeWith(result: Result) {
62 | val outcome = invokeSuspend()
63 | if (outcome === COROUTINE_SUSPENDED) return
64 | continuation.resume(outcome)
65 | }
66 |
67 | fun invokeSuspend(): Any {
68 | return foo(this)
69 | }
70 |
71 | override val context: CoroutineContext = EmptyCoroutineContext
72 | }
73 |
74 | val cont = (continuation as? FooContinuation) ?: FooContinuation()
75 | return when (cont.label) {
76 | 0 -> {
77 | val delay: suspend (Long) -> Unit = ::delay
78 |
79 | @Suppress("UNCHECKED_CAST")
80 | val df = delay as Function2, Any>
81 | cont.label++
82 | df(1000, cont)
83 | COROUTINE_SUSPENDED
84 | }
85 | 1 -> 1 // return 1
86 | else -> error("shouldn't happen")
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/src/test/kotlin/CustomConsumerTest.kt:
--------------------------------------------------------------------------------
1 | import kotlinx.coroutines.*
2 | import kotlinx.coroutines.flow.Flow
3 | import kotlinx.coroutines.flow.MutableStateFlow
4 | import kotlinx.coroutines.flow.StateFlow
5 | import kotlinx.coroutines.flow.collect
6 | import kotlinx.html.*
7 | import org.w3c.dom.events.Event
8 | import org.w3c.dom.html.HTMLElement
9 | import kotlin.coroutines.CoroutineContext
10 | import kotlin.coroutines.EmptyCoroutineContext
11 | import kotlin.coroutines.coroutineContext
12 |
13 | class TestConsumer : TagConsumer {
14 | override fun finalize() {
15 | TODO("Not yet implemented")
16 | }
17 |
18 | override fun onTagAttributeChange(tag: Tag, attribute: String, value: String?) {
19 | println("tag: $tag")
20 | println("attribute: $attribute")
21 | println("value: $value")
22 | }
23 |
24 | override fun onTagComment(content: CharSequence) {
25 | TODO("Not yet implemented")
26 | }
27 |
28 | override fun onTagContent(content: CharSequence) {
29 | println("content: $content")
30 | }
31 |
32 | override fun onTagContentEntity(entity: Entities) {
33 | TODO("Not yet implemented")
34 | }
35 |
36 | override fun onTagContentUnsafe(block: Unsafe.() -> Unit) {
37 | TODO("Not yet implemented")
38 | }
39 |
40 | override fun onTagEnd(tag: Tag) {
41 | println("tag end: $tag")
42 | }
43 |
44 | override fun onTagEvent(tag: Tag, event: String, value: (Event) -> Unit) {
45 | TODO("Not yet implemented")
46 | }
47 |
48 | override fun onTagStart(tag: Tag) {
49 | println("<${tag.tagName}> start: $tag")
50 | }
51 |
52 | suspend fun observe(data: Flow) {
53 | data.collect {
54 | println("change observed: $it")
55 | }
56 | }
57 |
58 | fun registerDynamic(value: Any) {
59 | println("registering dynamic $value")
60 | }
61 | }
62 |
63 | @ExperimentalCoroutinesApi
64 | class ObservableContent(content: Any) :
65 | CharSequence by content.toString(),
66 | MutableStateFlow by MutableStateFlow(content.toString()) {
67 | }
68 |
69 | @ExperimentalCoroutinesApi
70 | suspend fun main() {
71 | coroutineScope {
72 | val consumer = TestConsumer()
73 | val counter = MutableStateFlow(0)
74 | HTML(mapOf(), consumer).apply {
75 | body {
76 | p(classes = "foo bar") {
77 | withReactive(counter, this@coroutineScope) { +"counter is $it" }
78 | }
79 | }
80 | }
81 | counter.value++
82 | }
83 | // while (true) {}
84 | }
85 |
86 |
87 | @ExperimentalCoroutinesApi
88 | fun Tag.withReactive(content: StateFlow, scope: CoroutineScope = GlobalScope, block: (CharSequence) -> Unit) {
89 | (consumer as? TestConsumer).also {
90 | // println("do reactive stuff")
91 | scope.launch {
92 | it?.observe(content)
93 | }
94 | }
95 | block(content.value.toString())
96 | }
97 |
98 |
99 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 |
88 | @rem Execute Gradle
89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
90 |
91 | :end
92 | @rem End local scope for the variables with windows NT shell
93 | if "%ERRORLEVEL%"=="0" goto mainEnd
94 |
95 | :fail
96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
97 | rem the _cmd.exe /c_ return code!
98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
99 | exit /b 1
100 |
101 | :mainEnd
102 | if "%OS%"=="Windows_NT" endlocal
103 |
104 | :omega
105 |
--------------------------------------------------------------------------------
/src/main/kotlin/algorithms/leetcode/GoodPair.kt:
--------------------------------------------------------------------------------
1 | package algorithms.leetcode
2 |
3 | import java.util.HashMap
4 |
5 |
6 | fun countNicePairs(nums: IntArray): Int {
7 | // int[] sub = new int[nums.length];
8 | val map: MutableMap = HashMap()
9 | for (i in nums.indices) {
10 | val result = nums[i] - rev(nums[i])
11 | val newValue = map.getOrDefault(result, 0) + 1
12 | map[result] = newValue
13 | }
14 | var ret = 0
15 | for (n in map.values) {
16 | if (n > 1)
17 | ret += fact(n) / (fact(n - 2) * 2)
18 | }
19 | return ret
20 | // return fact(n) / fact(n - 1);
21 |
22 | //int[] revs = new int[nums.length];
23 | //for (int i = 0; i < nums.length; i++) {
24 | // revs[i] = rev(nums[i]);
25 | //}
26 | //int ret = 0;
27 | //for (int i = 0; i < nums.length; i++) {
28 | // for (int j = i + 1; j < nums.length; j++) {
29 | // if (nums[i] + revs[j] == nums[j] + revs[i]) {
30 | // ret++;
31 | // }
32 | // }
33 | //}
34 | //return ret;
35 | }
36 |
37 | private fun c(n: Int): Int {
38 | // n *
39 |
40 | TODO()
41 | }
42 |
43 | private fun fact(n: Int): Int {
44 | var ret = 1
45 | for (i in 1..n) ret *= i
46 | return ret
47 | }
48 |
49 | private fun rev(n: Int): Int {
50 | var n = n
51 | var ret = 0
52 | val t = 10
53 | while (n != 0) {
54 | ret = ret * 10 + n % t
55 | n /= 10
56 | }
57 | return ret
58 | }
59 |
60 |
61 | fun main() {
62 | countNicePairs(intArrayOf(8047408,
63 | 192867140,
64 | 497837845,
65 | 279787822,
66 | 151999002,
67 | 168514912,
68 | 193424242,
69 | 399636844,
70 | 132424231,
71 | 476736524,
72 | 267958611,
73 | 493350382,
74 | 476382727,
75 | 232939232,
76 | 197000791,
77 | 295291645,
78 | 126313621,
79 | 374645524,
80 | 7956597,
81 | 1376731,
82 | 496463745,
83 | 234481430,
84 | 359130803,
85 | 287625836,
86 | 250572050,
87 | 42311324,
88 | 477434624,
89 | 493231448,
90 | 493231244,
91 | 150494051,
92 | 184645534,
93 | 365252413,
94 | 495764582,
95 | 335976531,
96 | 384564332,
97 | 377151623,
98 | 198736741,
99 | 335161533,
100 | 245552540,
101 | 194897341,
102 | 83911938,
103 | 220562020,
104 | 496645745,
105 | 287151782,
106 | 374635526,
107 | 372483324,
108 | 485101584,
109 | 271797172,
110 | 244949442,
111 | 254333303,
112 | 251635002,
113 | 459181805,
114 | 472392123,
115 | 241350140,
116 | 256121502,
117 | 336895621,
118 | 354635302,
119 | 358909704,
120 | 194525491,
121 | 3606063,
122 | 194150341,
123 | 63477436,
124 | 341936141,
125 | 60299206,
126 | 69811896,
127 | 369928813,
128 | 229926920,
129 | 435310522,
130 | 299542980,
131 | 463777364,
132 | 164534512,
133 | 305885501,
134 | 437181734,
135 | 74288247,
136 | 487281835,
137 | 171161022,
138 | 423966312,
139 | 496989544,
140 | 452633252,
141 | 252433101,
142 | 141565141,
143 | 315895501,
144 | 478897927,
145 | 232532230,
146 | 472451262,
147 | 160504114,
148 | 476666674,
149 | 6179716,
150 | 251483002,
151 | 474777474,
152 | 443532332,
153 | 475808424,
154 | 457514604,
155 | 400936002,
156 | 384878483,
157 | 172616122,
158 | 283292232,
159 | 165645615,
160 | 392000144,
161 | 378636873))
162 | // countNicePairs(intArrayOf(432835222, 112141211, 5408045, 456281503, 283322436, 414281561, 37773, 286505682))
163 | // fact(3).also {println(it)}
164 | // countNicePairs(intArrayOf(42,11,1,97)).also { println(it) }
165 | // countNicePairs(intArrayOf(13,10,35,24,76)).also{ println(it) }
166 | }
--------------------------------------------------------------------------------
/src/main/kotlin/coroutine/flow/FunctionalReactiveUI.kt:
--------------------------------------------------------------------------------
1 | package coroutine.flow
2 |
3 | import coroutine.log
4 | import kotlinx.coroutines.*
5 | import kotlinx.coroutines.flow.*
6 |
7 | sealed class UiAction {
8 | object Refresh : UiAction()
9 | class LikeArticle(val position: Int) : UiAction()
10 | class SearchQuery(val value: String) : UiAction()
11 | }
12 |
13 | data class UiState(
14 | var likedPosition: Int? = null,
15 | var query: String? = null,
16 | var loading: Boolean = false
17 | )
18 |
19 | fun Flow.handleLike(state: UiState) = transform {
20 | emit(state.apply { loading = true })
21 | log("call like api, position: ${it.position}")
22 | delay(500)
23 | emit(state.apply { likedPosition = it.position; loading = false })
24 | }
25 |
26 | fun Flow.test1(): Flow = transform {
27 | log("in test1 LikeArticleTransformer")
28 | emit(UiState().apply { likedPosition = it.position })
29 | }
30 |
31 | fun Flow.handleSearch(state: UiState) = transform {
32 | emit(state.apply { loading = true })
33 | log("call search api, query: ${it.value}")
34 | delay(200)
35 | emit(state.apply { query = it.value; loading = false })
36 | }
37 |
38 | fun Flow.test2() = transform {
39 | log("in test2 SearchQueryTransformer")
40 | emit(UiState().apply { query = it.value })
41 | }
42 |
43 | @ExperimentalCoroutinesApi
44 | suspend fun main() {
45 | val refresh = MutableSharedFlow()
46 | val like = MutableSharedFlow()
47 | val search = MutableSharedFlow()
48 |
49 | coroutineScope {
50 | launch {
51 | delay(500); like.emit(UiAction.LikeArticle(1))
52 | delay(500); search.emit(UiAction.SearchQuery("foo"))
53 | delay(500); like.emit(UiAction.LikeArticle(2))
54 | delay(500); search.emit(UiAction.SearchQuery("bar"))
55 | }
56 |
57 | val flow = merge(refresh, like, search).shareIn(GlobalScope, SharingStarted.Eagerly)
58 |
59 |
60 | val flow2 = flow.scan(UiState()) { state, action ->
61 | when (action) {
62 | is UiAction.Refresh -> state
63 | is UiAction.LikeArticle -> state.apply { likedPosition = action.position }
64 | is UiAction.SearchQuery -> state.apply { query = action.value }
65 | }
66 | }
67 |
68 | val flow3: Flow = flow.flatMapLatest {
69 | log("in flatMapLatest: $it")
70 | merge(
71 | flow.map { log("1 here is $it"); it }.filterIsInstance().test1(),
72 | flow.map { log("2 here is $it");it }.filterIsInstance().map { UiState(query = "in map") },
73 | flow.map { log("3 here is $it");it }.filterIsInstance().map { log("in map 3");it }
74 | .test2(),
75 | // flowOf(UiState(query = "static"))
76 | ).onEach {
77 | log("in onEach $it")
78 | }
79 | }
80 |
81 |
82 | val flow4 = merge(
83 | flow.filterIsInstance().test1(),
84 | flow.filterIsInstance