[BAEL-19883] - Move articles out of core-kotlin part2
This commit is contained in:
13
core-kotlin-modules/core-kotlin-lang-2/README.md
Normal file
13
core-kotlin-modules/core-kotlin-lang-2/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Core Kotlin Lang
|
||||
|
||||
This module contains articles about core features in the Kotlin language.
|
||||
|
||||
### Relevant articles:
|
||||
- [Kotlin return, break, continue Keywords](https://www.baeldung.com/kotlin-return-break-continue)
|
||||
- [Infix Functions in Kotlin](https://www.baeldung.com/kotlin-infix-functions)
|
||||
- [Lambda Expressions in Kotlin](https://www.baeldung.com/kotlin-lambda-expressions)
|
||||
- [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final)
|
||||
- [Initializing Arrays in Kotlin](https://www.baeldung.com/kotlin-initialize-array)
|
||||
- [Lazy Initialization in Kotlin](https://www.baeldung.com/kotlin-lazy-initialization)
|
||||
- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin-null-safety)
|
||||
- [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang)
|
||||
16
core-kotlin-modules/core-kotlin-lang-2/pom.xml
Normal file
16
core-kotlin-modules/core-kotlin-lang-2/pom.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-kotlin-lang-2</artifactId>
|
||||
<name>core-kotlin-lang-2</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-kotlin-modules</groupId>
|
||||
<artifactId>core-kotlin-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.lazy;
|
||||
|
||||
public class ClassWithHeavyInitialization {
|
||||
private ClassWithHeavyInitialization() {
|
||||
}
|
||||
|
||||
private static class LazyHolder {
|
||||
public static final ClassWithHeavyInitialization INSTANCE = new ClassWithHeavyInitialization();
|
||||
}
|
||||
|
||||
public static ClassWithHeavyInitialization getInstance() {
|
||||
return LazyHolder.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.baeldung.lambda
|
||||
|
||||
fun inferredType(input: Int): Int {
|
||||
val square = { number: Int -> number * number }
|
||||
|
||||
return square(input)
|
||||
}
|
||||
|
||||
fun intToBiggerString(argument: Int): String {
|
||||
|
||||
val magnitude100String = { input: Int ->
|
||||
val magnitude = input * 100
|
||||
magnitude.toString()
|
||||
}
|
||||
|
||||
return magnitude100String(argument)
|
||||
}
|
||||
|
||||
fun manyLambda(nums: Array<Int>): List<String> {
|
||||
val newList = nums.map { intToBiggerString(it) }
|
||||
|
||||
return newList
|
||||
}
|
||||
|
||||
fun empty() {
|
||||
val noReturn: (Int) -> Unit = { num -> println(num) }
|
||||
|
||||
noReturn(5)
|
||||
}
|
||||
|
||||
fun invokeLambda(lambda: (Double) -> Boolean): Boolean {
|
||||
return lambda(4.329)
|
||||
}
|
||||
|
||||
fun extendString(arg: String, num: Int): String {
|
||||
val another: String.(Int) -> String = { this + it }
|
||||
|
||||
return arg.another(num)
|
||||
}
|
||||
|
||||
fun getCalculationLambda(): (Int) -> Any {
|
||||
val calculateGrade = { grade: Int ->
|
||||
when (grade) {
|
||||
in 0..40 -> "Fail"
|
||||
in 41..70 -> "Pass"
|
||||
in 71..100 -> "Distinction"
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
return calculateGrade
|
||||
}
|
||||
|
||||
fun getCalculationLambdaWithReturn(): (Int) -> String {
|
||||
val calculateGrade: Int.() -> String = lambda@{
|
||||
if (this < 0 || this > 100) {
|
||||
return@lambda "Error"
|
||||
} else if (this < 40) {
|
||||
return@lambda "Fail"
|
||||
} else if (this < 70) {
|
||||
return@lambda "Pass"
|
||||
}
|
||||
|
||||
"Distinction"
|
||||
}
|
||||
|
||||
return calculateGrade
|
||||
}
|
||||
|
||||
fun getCalculationAnonymousFunction(): (Int) -> String {
|
||||
val calculateGrade = fun(grade: Int): String {
|
||||
if (grade < 0 || grade > 100) {
|
||||
return "Error"
|
||||
} else if (grade < 40) {
|
||||
return "Fail"
|
||||
} else if (grade < 70) {
|
||||
return "Pass"
|
||||
}
|
||||
|
||||
return "Distinction"
|
||||
}
|
||||
|
||||
return calculateGrade
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.lazy;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
|
||||
public class LazyJavaUnitTest {
|
||||
|
||||
@Test
|
||||
public void giveHeavyClass_whenInitLazy_thenShouldReturnInstanceOnFirstCall() {
|
||||
//when
|
||||
ClassWithHeavyInitialization classWithHeavyInitialization = ClassWithHeavyInitialization.getInstance();
|
||||
ClassWithHeavyInitialization classWithHeavyInitialization2 = ClassWithHeavyInitialization.getInstance();
|
||||
|
||||
//then
|
||||
assertTrue(classWithHeavyInitialization == classWithHeavyInitialization2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.baeldung.arrayinitialization
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ArrayInitializationTest {
|
||||
|
||||
@Test
|
||||
fun givenArrayOfStrings_thenValuesPopulated() {
|
||||
val strings = arrayOf("January", "February", "March")
|
||||
|
||||
assertEquals(3, strings.size)
|
||||
assertEquals("March", strings[2])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenArrayOfIntegers_thenValuesPopulated() {
|
||||
val integers = intArrayOf(1, 2, 3, 4)
|
||||
|
||||
assertEquals(4, integers.size)
|
||||
assertEquals(1, integers[0])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenArrayOfNulls_whenPopulated_thenValuesPresent() {
|
||||
val array = arrayOfNulls<Number>(5)
|
||||
|
||||
for (i in array.indices) {
|
||||
array[i] = i * i
|
||||
}
|
||||
|
||||
assertEquals(16, array[4])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenGeneratorUsed_thenValuesPresent() {
|
||||
val generatedArray = IntArray(10) { i -> i * i }
|
||||
|
||||
assertEquals(81, generatedArray[9])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenStringGenerated_thenValuesPresent() {
|
||||
val generatedStringArray = Array(10) { i -> "Number of index: $i" }
|
||||
|
||||
assertEquals("Number of index: 0", generatedStringArray[0])
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.constant
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ConstantUnitTest {
|
||||
|
||||
@Test
|
||||
fun givenConstant_whenCompareWithActualValue_thenReturnTrue() {
|
||||
assertEquals(10, TestKotlinConstantObject.COMPILE_TIME_CONST)
|
||||
assertEquals(30, TestKotlinConstantObject.RUN_TIME_CONST)
|
||||
assertEquals(20, TestKotlinConstantObject.JAVA_STATIC_FINAL_FIELD)
|
||||
|
||||
assertEquals(40, TestKotlinConstantClass.COMPANION_OBJECT_NUMBER)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.constant
|
||||
|
||||
|
||||
class TestKotlinConstantClass {
|
||||
companion object {
|
||||
const val COMPANION_OBJECT_NUMBER = 40
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.constant
|
||||
|
||||
|
||||
object TestKotlinConstantObject {
|
||||
const val COMPILE_TIME_CONST = 10
|
||||
|
||||
val RUN_TIME_CONST: Int
|
||||
|
||||
@JvmField
|
||||
val JAVA_STATIC_FINAL_FIELD = 20
|
||||
|
||||
init {
|
||||
RUN_TIME_CONST = TestKotlinConstantObject.COMPILE_TIME_CONST + 20;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.infixfunctions
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
class InfixFunctionsTest {
|
||||
@Test
|
||||
fun testColours() {
|
||||
val color = 0x123456
|
||||
val red = (color and 0xff0000) shr 16
|
||||
val green = (color and 0x00ff00) shr 8
|
||||
val blue = (color and 0x0000ff) shr 0
|
||||
|
||||
Assert.assertEquals(0x12, red)
|
||||
Assert.assertEquals(0x34, green)
|
||||
Assert.assertEquals(0x56, blue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNewAssertions() {
|
||||
class Assertion<T>(private val target: T) {
|
||||
infix fun isEqualTo(other: T) {
|
||||
Assert.assertEquals(other, target)
|
||||
}
|
||||
|
||||
infix fun isDifferentFrom(other: T) {
|
||||
Assert.assertNotEquals(other, target)
|
||||
}
|
||||
}
|
||||
|
||||
val result = Assertion(5)
|
||||
|
||||
result isEqualTo 5
|
||||
|
||||
// The following two lines are expected to fail
|
||||
// result isEqualTo 6
|
||||
// result isDifferentFrom 5
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNewStringMethod() {
|
||||
infix fun String.substringMatches(r: Regex) : List<String> {
|
||||
return r.findAll(this)
|
||||
.map { it.value }
|
||||
.toList()
|
||||
}
|
||||
|
||||
val matches = "a bc def" substringMatches ".*? ".toRegex()
|
||||
Assert.assertEquals(listOf("a ", "bc "), matches)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.baeldung.lambda;
|
||||
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Created by Paul Jervis on 24/04/2018.
|
||||
*/
|
||||
class LambdaKotlinUnitTest {
|
||||
|
||||
@Test
|
||||
void givenJava6_whenUsingAnonnymousClass_thenReturnLambdaResult() {
|
||||
assertTrue(LambdaKt.invokeLambda(new Function1<Double, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(Double c) {
|
||||
return c >= 0;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenJava8_whenUsingLambda_thenReturnLambdaResult() {
|
||||
assertTrue(LambdaKt.invokeLambda(c -> c >= 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenJava8_whenCallingMethodWithStringExtension_thenImplementExtension() {
|
||||
String actual = LambdaKt.extendString("Word", 90);
|
||||
String expected = "Word90";
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package com.baeldung.lambda
|
||||
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class LambdaTest {
|
||||
|
||||
@Test
|
||||
fun whenCallingALambda_thenPerformTheAction() {
|
||||
assertEquals(9, inferredType(3))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCallingAMoreComplicatedLambda_thenPerformTheAction() {
|
||||
assertEquals("500", intToBiggerString(5))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenPassingALambdaObject_thenCallTriggerLambda() {
|
||||
val lambda = { arg: Double ->
|
||||
arg == 4.329
|
||||
}
|
||||
|
||||
val result = invokeLambda(lambda)
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenPassingALambdaLiteral_thenCallTriggerLambda() {
|
||||
val result = invokeLambda({
|
||||
true
|
||||
})
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenPassingALambdaLiteralOutsideBrackets_thenCallTriggerLambda() {
|
||||
val result = invokeLambda { arg -> arg.isNaN() }
|
||||
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenPassingAnAnonymousFunction_thenCallTriggerLambda() {
|
||||
val result = invokeLambda(fun(arg: Double): Boolean {
|
||||
return arg >= 0
|
||||
})
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenUsingLambda_thenCalculateGrade() {
|
||||
val gradeCalculation = getCalculationLambda()
|
||||
|
||||
assertEquals(false, gradeCalculation(-40))
|
||||
assertEquals("Pass", gradeCalculation(50))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenUsingReturnStatementLambda_thenCalculateGrade() {
|
||||
val gradeCalculation: Int.() -> String = getCalculationLambdaWithReturn()
|
||||
|
||||
assertEquals("Distinction", 80.gradeCalculation())
|
||||
assertEquals("Error", 244_234_324.gradeCalculation())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenUsingAnonymousFunction_thenCalculateGrade() {
|
||||
val gradeCalculation = getCalculationAnonymousFunction()
|
||||
|
||||
assertEquals("Error", gradeCalculation(244_234_324))
|
||||
assertEquals("Pass", gradeCalculation(50))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenPassingAFunctionReference_thenCallTriggerLambda() {
|
||||
val reference = Double::isFinite
|
||||
val result = invokeLambda(reference)
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenArray_whenMappingArray_thenPerformCalculationOnAllElements() {
|
||||
val expected = listOf("100", "200", "300", "400", "500")
|
||||
val actual = manyLambda(arrayOf(1, 2, 3, 4, 5))
|
||||
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.baeldung.lazy
|
||||
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class LazyUnitTest {
|
||||
@Test
|
||||
fun givenLazyValue_whenGetIt_thenShouldInitializeItOnlyOnce() {
|
||||
//given
|
||||
val numberOfInitializations: AtomicInteger = AtomicInteger()
|
||||
val lazyValue: ClassWithHeavyInitialization by lazy {
|
||||
numberOfInitializations.incrementAndGet()
|
||||
ClassWithHeavyInitialization()
|
||||
}
|
||||
//when
|
||||
println(lazyValue)
|
||||
println(lazyValue)
|
||||
|
||||
//then
|
||||
assertEquals(numberOfInitializations.get(), 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLazyValue_whenGetItUsingPublication_thenCouldInitializeItMoreThanOnce() {
|
||||
//given
|
||||
val numberOfInitializations: AtomicInteger = AtomicInteger()
|
||||
val lazyValue: ClassWithHeavyInitialization by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
numberOfInitializations.incrementAndGet()
|
||||
ClassWithHeavyInitialization()
|
||||
}
|
||||
val executorService = Executors.newFixedThreadPool(2)
|
||||
val countDownLatch = CountDownLatch(1)
|
||||
//when
|
||||
executorService.submit { countDownLatch.await(); println(lazyValue) }
|
||||
executorService.submit { countDownLatch.await(); println(lazyValue) }
|
||||
countDownLatch.countDown()
|
||||
|
||||
//then
|
||||
executorService.shutdown()
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS)
|
||||
//assertEquals(numberOfInitializations.get(), 2)
|
||||
}
|
||||
|
||||
class ClassWithHeavyInitialization {
|
||||
|
||||
}
|
||||
|
||||
|
||||
lateinit var a: String
|
||||
@Test
|
||||
fun givenLateInitProperty_whenAccessItAfterInit_thenPass() {
|
||||
//when
|
||||
a = "it"
|
||||
println(a)
|
||||
|
||||
//then not throw
|
||||
}
|
||||
|
||||
@Test(expected = UninitializedPropertyAccessException::class)
|
||||
fun givenLateInitProperty_whenAccessItWithoutInit_thenThrow() {
|
||||
//when
|
||||
println(a)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.baeldung.nullsafety
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
class NullSafetyTest {
|
||||
|
||||
@Test
|
||||
fun givenNonNullableField_whenAssignValueToIt_thenNotNeedToCheckAgainstNull() {
|
||||
//given
|
||||
var a: String = "value"
|
||||
//a = null compilation error
|
||||
|
||||
//then
|
||||
assertEquals(a.length, 5)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableField_whenReadValue_thenNeedToCheckAgainstNull() {
|
||||
//given
|
||||
var b: String? = "value"
|
||||
b = null
|
||||
|
||||
//when
|
||||
if (b != null) {
|
||||
|
||||
} else {
|
||||
assertNull(b)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithValue() {
|
||||
//given
|
||||
val p: Person? = Person(Country("ENG"))
|
||||
|
||||
//when
|
||||
val res = p?.country?.code
|
||||
|
||||
//then
|
||||
assertEquals(res, "ENG")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithNull() {
|
||||
//given
|
||||
val p: Person? = Person(Country(null))
|
||||
|
||||
//when
|
||||
val res = p?.country?.code
|
||||
|
||||
//then
|
||||
assertNull(res)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenCollectionOfObjects_whenUseLetOperator_thenShouldApplyActionOnlyOnNonNullValue() {
|
||||
//given
|
||||
val firstName = "Tom"
|
||||
val secondName = "Michael"
|
||||
val names: List<String?> = listOf(firstName, null, secondName)
|
||||
|
||||
//when
|
||||
var res = listOf<String?>()
|
||||
for (item in names) {
|
||||
item?.let { res = res.plus(it); it }
|
||||
?.also{it -> println("non nullable value: $it")}
|
||||
}
|
||||
|
||||
//then
|
||||
assertEquals(2, res.size)
|
||||
assertTrue { res.contains(firstName) }
|
||||
assertTrue { res.contains(secondName) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fivenCollectionOfObject_whenUseRunOperator_thenExecuteActionOnNonNullValue(){
|
||||
//given
|
||||
val firstName = "Tom"
|
||||
val secondName = "Michael"
|
||||
val names: List<String?> = listOf(firstName, null, secondName)
|
||||
|
||||
//when
|
||||
var res = listOf<String?>()
|
||||
for (item in names) {
|
||||
item?.run{res = res.plus(this)}
|
||||
}
|
||||
|
||||
//then
|
||||
assertEquals(2, res.size)
|
||||
assertTrue { res.contains(firstName) }
|
||||
assertTrue { res.contains(secondName) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableReference_whenUseElvisOperator_thenShouldReturnValueIfReferenceIsNotNull() {
|
||||
//given
|
||||
val value: String? = "name"
|
||||
|
||||
//when
|
||||
val res = value?.length ?: -1
|
||||
|
||||
//then
|
||||
assertEquals(res, 4)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableReference_whenUseElvisOperator_thenShouldReturnDefaultValueIfReferenceIsNull() {
|
||||
//given
|
||||
val value: String? = null
|
||||
|
||||
//when
|
||||
val res = value?.length ?: -1
|
||||
|
||||
//then
|
||||
assertEquals(res, -1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNull_thenThrowNPE() {
|
||||
//given
|
||||
var b: String? = "value"
|
||||
b = null
|
||||
|
||||
//when
|
||||
assertFailsWith<NullPointerException> {
|
||||
b!!.length
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNotNull_thenReturnValue() {
|
||||
//given
|
||||
val b: String? = "value"
|
||||
|
||||
//then
|
||||
assertEquals(b!!.length, 5)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenNullableList_whenUseFilterNotNullMethod_thenRemoveALlNullValues() {
|
||||
//given
|
||||
val list: List<String?> = listOf("a", null, "b")
|
||||
|
||||
//when
|
||||
val res = list.filterNotNull()
|
||||
|
||||
//then
|
||||
assertEquals(res.size, 2)
|
||||
assertTrue { res.contains("a") }
|
||||
assertTrue { res.contains("b") }
|
||||
}
|
||||
}
|
||||
|
||||
data class Person(val country: Country?)
|
||||
|
||||
data class Country(val code: String?)
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.baeldung.structuraljump
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
class StructuralJumpUnitTest {
|
||||
|
||||
@Test
|
||||
fun givenLoop_whenBreak_thenComplete() {
|
||||
var value = ""
|
||||
for (i in "hello_world") {
|
||||
if (i == '_')
|
||||
break
|
||||
value += i.toString()
|
||||
}
|
||||
assertEquals("hello", value)
|
||||
}
|
||||
@Test
|
||||
fun givenLoop_whenBreakWithLabel_thenComplete() {
|
||||
var value = ""
|
||||
outer_loop@ for (i in 'a'..'d') {
|
||||
for (j in 1..3) {
|
||||
value += "" + i + j
|
||||
if (i == 'b' && j == 1)
|
||||
break@outer_loop
|
||||
}
|
||||
}
|
||||
assertEquals("a1a2a3b1", value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLoop_whenContinue_thenComplete() {
|
||||
var result = ""
|
||||
for (i in "hello_world") {
|
||||
if (i == '_')
|
||||
continue
|
||||
result += i
|
||||
}
|
||||
assertEquals("helloworld", result)
|
||||
}
|
||||
@Test
|
||||
fun givenLoop_whenContinueWithLabel_thenComplete() {
|
||||
var result = ""
|
||||
outer_loop@ for (i in 'a'..'c') {
|
||||
for (j in 1..3) {
|
||||
if (i == 'b')
|
||||
continue@outer_loop
|
||||
result += "" + i + j
|
||||
}
|
||||
}
|
||||
assertEquals("a1a2a3c1c2c3", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLambda_whenReturn_thenComplete() {
|
||||
var result = returnInLambda();
|
||||
assertEquals("hello", result)
|
||||
}
|
||||
|
||||
private fun returnInLambda(): String {
|
||||
var result = ""
|
||||
"hello_world".forEach {
|
||||
// non-local return directly to the caller
|
||||
if (it == '_') return result
|
||||
result += it.toString()
|
||||
}
|
||||
//this line won't be reached
|
||||
return result;
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLambda_whenReturnWithExplicitLabel_thenComplete() {
|
||||
var result = ""
|
||||
"hello_world".forEach lit@{
|
||||
if (it == '_') {
|
||||
// local return to the caller of the lambda, i.e. the forEach loop
|
||||
return@lit
|
||||
}
|
||||
result += it.toString()
|
||||
}
|
||||
assertEquals("helloworld", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenLambda_whenReturnWithImplicitLabel_thenComplete() {
|
||||
var result = ""
|
||||
"hello_world".forEach {
|
||||
if (it == '_') {
|
||||
// local return to the caller of the lambda, i.e. the forEach loop
|
||||
return@forEach
|
||||
}
|
||||
result += it.toString()
|
||||
}
|
||||
assertEquals("helloworld", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAnonymousFunction_return_thenComplete() {
|
||||
var result = ""
|
||||
"hello_world".forEach(fun(element) {
|
||||
// local return to the caller of the anonymous fun, i.e. the forEach loop
|
||||
if (element == '_') return
|
||||
result += element.toString()
|
||||
})
|
||||
assertEquals("helloworld", result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAnonymousFunction_returnToLabel_thenComplete() {
|
||||
var result = ""
|
||||
run loop@{
|
||||
"hello_world".forEach {
|
||||
// non-local return from the lambda passed to run
|
||||
if (it == '_') return@loop
|
||||
result += it.toString()
|
||||
}
|
||||
}
|
||||
assertEquals("hello", result)
|
||||
}
|
||||
}
|
||||
16
core-kotlin-modules/core-kotlin-lang/README.md
Normal file
16
core-kotlin-modules/core-kotlin-lang/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## Core Kotlin Lang
|
||||
|
||||
This module contains articles about core features in the Kotlin language.
|
||||
|
||||
### Relevant articles:
|
||||
- [Guide to the “when{}” Block in Kotlin](https://www.baeldung.com/kotlin-when)
|
||||
- [Difference Between “==” and “===” Operators in Kotlin](https://www.baeldung.com/kotlin-equality-operators)
|
||||
- [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach)
|
||||
- [Destructuring Declarations in Kotlin](https://www.baeldung.com/kotlin-destructuring-declarations)
|
||||
- [Try-with-resources in Kotlin](https://www.baeldung.com/kotlin-try-with-resources)
|
||||
- [Operator Overloading in Kotlin](https://www.baeldung.com/kotlin-operator-overloading)
|
||||
- [Inline Functions in Kotlin](https://www.baeldung.com/kotlin-inline-functions)
|
||||
- [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type)
|
||||
- [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges)
|
||||
- [Creating a Kotlin Range Iterator on a Custom Object](https://www.baeldung.com/kotlin-custom-range-iterator)
|
||||
- [[More --> ]](/core-kotlin-modules/core-kotlin-lang-2)
|
||||
16
core-kotlin-modules/core-kotlin-lang/pom.xml
Normal file
16
core-kotlin-modules/core-kotlin-lang/pom.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>core-kotlin-lang</artifactId>
|
||||
<name>core-kotlin-lang</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-kotlin-modules</groupId>
|
||||
<artifactId>core-kotlin-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.baeldung.destructuringdeclarations
|
||||
|
||||
data class Person(var id: Int, var name: String, var age: Int)
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.baeldung.destructuringdeclarations
|
||||
|
||||
data class Result(val result: Int, val status: String)
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.baeldung.destructuringdeclarations
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
//2.1. Objects
|
||||
val person = Person(1, "Jon Snow", 20)
|
||||
val(id, name, age) = person
|
||||
|
||||
println(id) //1
|
||||
println(name) //Jon Snow
|
||||
println(age) //20
|
||||
|
||||
//2.2. Functions
|
||||
fun getPersonInfo() = Person(2, "Ned Stark", 45)
|
||||
val(idf, namef, agef) = getPersonInfo()
|
||||
|
||||
fun twoValuesReturn(): Pair<Int, String> {
|
||||
|
||||
// needed code
|
||||
|
||||
return Pair(1, "success")
|
||||
}
|
||||
|
||||
// Now, to use this function:
|
||||
val (result, status) = twoValuesReturn()
|
||||
|
||||
//2.3. Collections and For-loops
|
||||
var map: HashMap<Int, Person> = HashMap()
|
||||
map.put(1, person)
|
||||
|
||||
for((key, value) in map){
|
||||
println("Key: $key, Value: $value")
|
||||
}
|
||||
|
||||
//2.4. Underscore and Destructuring in Lambdas
|
||||
val (_, name2, age2) = person
|
||||
val (id3, name3) = person
|
||||
|
||||
map.mapValues { entry -> "${entry.value}!" }
|
||||
map.mapValues { (key, value) -> "$value!" }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package com.baeldung.equalityoperators
|
||||
|
||||
data class User(val name: String, val age: Int, val hobbies: List<String>)
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.baeldung.forEach
|
||||
|
||||
|
||||
class Country(val name : String, val cities : List<City>)
|
||||
|
||||
class City(val name : String, val streets : List<String>)
|
||||
|
||||
fun City.getStreetsWithCityName() : List<String> {
|
||||
return streets.map { "$name, $it" }.toList()
|
||||
}
|
||||
|
||||
fun Country.getCitiesWithCountryName() : List<String> {
|
||||
return cities.flatMap { it.getStreetsWithCityName() }
|
||||
.map { "$name, $it" }
|
||||
}
|
||||
|
||||
class World {
|
||||
|
||||
private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht")
|
||||
private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten")
|
||||
private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof")
|
||||
private val countries = listOf(
|
||||
Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht),
|
||||
City("Amsterdam", streetsOfAmsterdam))),
|
||||
Country("Germany", listOf(City("Berlin", streetsOfBerlin))))
|
||||
|
||||
fun allCountriesIt() {
|
||||
countries.forEach { println(it.name) }
|
||||
}
|
||||
|
||||
fun allCountriesItExplicit() {
|
||||
countries.forEach { it -> println(it.name) }
|
||||
}
|
||||
|
||||
//here we cannot refer to 'it' anymore inside the forEach
|
||||
fun allCountriesExplicit() {
|
||||
countries.forEach { c -> println(c.name) }
|
||||
}
|
||||
|
||||
fun allNested() {
|
||||
countries.forEach {
|
||||
println(it.name)
|
||||
it.cities.forEach {
|
||||
println(" ${it.name}")
|
||||
it.streets.forEach { println(" $it") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun allTable() {
|
||||
countries.forEach { c ->
|
||||
c.cities.forEach { p ->
|
||||
p.streets.forEach { println("${c.name} ${p.name} $it") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun allStreetsFlatMap() {
|
||||
|
||||
countries.flatMap { it.cities}
|
||||
.flatMap { it.streets}
|
||||
.forEach { println(it) }
|
||||
}
|
||||
|
||||
fun allFlatMapTable() {
|
||||
|
||||
countries.flatMap { it.getCitiesWithCountryName() }
|
||||
.forEach { println(it) }
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
|
||||
val world = World()
|
||||
|
||||
world.allCountriesExplicit()
|
||||
|
||||
world.allNested()
|
||||
|
||||
world.allTable()
|
||||
|
||||
world.allStreetsFlatMap()
|
||||
|
||||
world.allFlatMapTable()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.inline
|
||||
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
* An extension function on all collections to apply a function to all collection
|
||||
* elements.
|
||||
*/
|
||||
fun <T> Collection<T>.each(block: (T) -> Unit) {
|
||||
for (e in this) block(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* In order to see the the JVM bytecode:
|
||||
* 1. Compile the Kotlin file using `kotlinc Inline.kt`
|
||||
* 2. Take a peek at the bytecode using the `javap -c InlineKt`
|
||||
*/
|
||||
fun main() {
|
||||
val numbers = listOf(1, 2, 3, 4, 5)
|
||||
val random = random()
|
||||
|
||||
numbers.each { println(random * it) } // capturing the random variable
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a random number.
|
||||
*/
|
||||
private fun random(): Int = Random.nextInt()
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
enum class Currency {
|
||||
DOLLARS, EURO
|
||||
}
|
||||
|
||||
class Money(val amount: BigDecimal, val currency: Currency) : Comparable<Money> {
|
||||
|
||||
override fun compareTo(other: Money): Int =
|
||||
convert(Currency.DOLLARS).compareTo(other.convert(Currency.DOLLARS))
|
||||
|
||||
fun convert(currency: Currency): BigDecimal = TODO()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Money) return false
|
||||
|
||||
if (amount != other.amount) return false
|
||||
if (currency != other.currency) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = amount.hashCode()
|
||||
result = 31 * result + currency.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
interface Page<T> {
|
||||
fun pageNumber(): Int
|
||||
fun pageSize(): Int
|
||||
fun elements(): MutableList<T>
|
||||
}
|
||||
|
||||
operator fun <T> Page<T>.get(index: Int): T = elements()[index]
|
||||
operator fun <T> Page<T>.get(start: Int, endExclusive: Int): List<T> = elements().subList(start, endExclusive)
|
||||
operator fun <T> Page<T>.set(index: Int, value: T) {
|
||||
elements()[index] = value
|
||||
}
|
||||
|
||||
operator fun <T> Page<T>.contains(element: T): Boolean = element in elements()
|
||||
operator fun <T> Page<T>.iterator() = elements().iterator()
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
data class Point(val x: Int, val y: Int)
|
||||
|
||||
operator fun Point.unaryMinus() = Point(-x, -y)
|
||||
operator fun Point.not() = Point(y, x)
|
||||
operator fun Point.inc() = Point(x + 1, y + 1)
|
||||
operator fun Point.dec() = Point(x - 1, y - 1)
|
||||
|
||||
operator fun Point.plus(other: Point): Point = Point(x + other.x, y + other.y)
|
||||
operator fun Point.minus(other: Point): Point = Point(x - other.x, y - other.y)
|
||||
operator fun Point.times(other: Point): Point = Point(x * other.x, y * other.y)
|
||||
operator fun Point.div(other: Point): Point = Point(x / other.x, y / other.y)
|
||||
operator fun Point.rem(other: Point): Point = Point(x % other.x, y % other.y)
|
||||
operator fun Point.times(factor: Int): Point = Point(x * factor, y * factor)
|
||||
operator fun Int.times(point: Point): Point = Point(point.x * this, point.y * this)
|
||||
|
||||
class Shape {
|
||||
val points = mutableListOf<Point>()
|
||||
|
||||
operator fun Point.unaryPlus() {
|
||||
points.add(this)
|
||||
}
|
||||
}
|
||||
|
||||
fun shape(init: Shape.() -> Unit): Shape {
|
||||
val shape = Shape()
|
||||
shape.init()
|
||||
|
||||
return shape
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
import java.math.BigInteger
|
||||
|
||||
operator fun <T> MutableCollection<T>.plusAssign(element: T) {
|
||||
add(element)
|
||||
}
|
||||
operator fun BigInteger.plus(other: Int): BigInteger = add(BigInteger("$other"))
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
for (ch in 'a'..'f') {
|
||||
print(ch)
|
||||
}
|
||||
println()
|
||||
|
||||
for (ch in 'f' downTo 'a') {
|
||||
print(ch)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.range
|
||||
|
||||
enum class Color(val rgb: Int) {
|
||||
BLUE(0x0000FF),
|
||||
GREEN(0x008000),
|
||||
RED(0xFF0000),
|
||||
MAGENTA(0xFF00FF),
|
||||
YELLOW(0xFFFF00);
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
println(Color.values().toList());
|
||||
val red = Color.RED
|
||||
val yellow = Color.YELLOW
|
||||
val range = red..yellow
|
||||
|
||||
println(range.contains(Color.MAGENTA))
|
||||
println(range.contains(Color.BLUE))
|
||||
println(range.contains(Color.GREEN))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val r = 1..10
|
||||
|
||||
//Apply filter
|
||||
val f = r.filter { it -> it % 2 == 0 }
|
||||
println(f)
|
||||
|
||||
//Map
|
||||
val m = r.map { it -> it * it }
|
||||
println(m)
|
||||
|
||||
//Reduce
|
||||
val rdc = r.reduce { a, b -> a + b }
|
||||
println(rdc)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
println((1..9).first)
|
||||
println((1..9 step 2).step)
|
||||
println((3..9).reversed().last)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
val r = 1..20
|
||||
println(r.min())
|
||||
println(r.max())
|
||||
println(r.sum())
|
||||
println(r.average())
|
||||
println(r.count())
|
||||
|
||||
val repeated = listOf(1, 1, 2, 4, 4, 6, 10)
|
||||
println(repeated.distinct())
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
for (i in 1..9) {
|
||||
print(i)
|
||||
}
|
||||
println()
|
||||
|
||||
for (i in 9 downTo 1) {
|
||||
print(i)
|
||||
}
|
||||
println()
|
||||
|
||||
for (i in 1.rangeTo(9)) {
|
||||
print(i)
|
||||
}
|
||||
println()
|
||||
|
||||
for (i in 9.downTo(1)) {
|
||||
print(i)
|
||||
}
|
||||
println()
|
||||
|
||||
for (i in 1 until 9) {
|
||||
print(i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
(1..9).reversed().forEach {
|
||||
print(it)
|
||||
}
|
||||
|
||||
println()
|
||||
|
||||
(1..9).reversed().step(3).forEach {
|
||||
print(it)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
for(i in 1..9 step 2){
|
||||
print(i)
|
||||
}
|
||||
|
||||
println()
|
||||
|
||||
for (i in 9 downTo 1 step 2){
|
||||
print(i)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.baeldung.range
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
for (i in 1 until 9) {
|
||||
print(i)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.baeldung.rangeiterator
|
||||
|
||||
import java.lang.IllegalStateException
|
||||
|
||||
class CustomColor(val rgb: Int): Comparable<CustomColor> {
|
||||
|
||||
override fun compareTo(other: CustomColor): Int {
|
||||
return this.rgb.compareTo(other.rgb)
|
||||
}
|
||||
|
||||
operator fun rangeTo(that: CustomColor) = ColorRange(this, that)
|
||||
|
||||
operator fun inc(): CustomColor {
|
||||
return CustomColor(rgb + 1)
|
||||
}
|
||||
|
||||
init {
|
||||
if(rgb < 0x000000 || rgb > 0xFFFFFF){
|
||||
throw IllegalStateException("RGB must be between 0 and 16777215")
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "CustomColor(rgb=$rgb)"
|
||||
}
|
||||
}
|
||||
class ColorRange(override val start: CustomColor,
|
||||
override val endInclusive: CustomColor) : ClosedRange<CustomColor>, Iterable<CustomColor>{
|
||||
|
||||
override fun iterator(): Iterator<CustomColor> {
|
||||
return ColorIterator(start, endInclusive)
|
||||
}
|
||||
}
|
||||
|
||||
class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator<CustomColor> {
|
||||
|
||||
var initValue = start
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return initValue <= endInclusive
|
||||
}
|
||||
|
||||
override fun next(): CustomColor {
|
||||
return initValue++
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val a = CustomColor(0xABCDEF)
|
||||
val b = CustomColor(-1)
|
||||
val c = CustomColor(0xABCDFF)
|
||||
|
||||
for(color in a..c){
|
||||
println(color)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.whenblock
|
||||
|
||||
enum class UnixFileType {
|
||||
D, HYPHEN_MINUS, L
|
||||
}
|
||||
|
||||
sealed class UnixFile {
|
||||
|
||||
abstract fun getFileType(): UnixFileType
|
||||
|
||||
class RegularFile(val content: String) : UnixFile() {
|
||||
override fun getFileType(): UnixFileType {
|
||||
return UnixFileType.HYPHEN_MINUS
|
||||
}
|
||||
}
|
||||
|
||||
class Directory(val children: List<UnixFile>) : UnixFile() {
|
||||
override fun getFileType(): UnixFileType {
|
||||
return UnixFileType.D
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolicLink(val originalFile: UnixFile) : UnixFile() {
|
||||
override fun getFileType(): UnixFileType {
|
||||
return UnixFileType.L
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.baeldung.equalityoperators
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class EqualityTest {
|
||||
|
||||
// Checks referential equality
|
||||
@Test
|
||||
fun givenTwoIntegers_whenCheckReference_thenEqualReference() {
|
||||
val a = Integer(10)
|
||||
val b = Integer(10)
|
||||
|
||||
assertFalse(a === b)
|
||||
}
|
||||
|
||||
// Checks structural equality
|
||||
@Test
|
||||
fun givenTwoIntegers_whenCheckValue_thenStructurallyEqual() {
|
||||
val a = Integer(10)
|
||||
val b = Integer(10)
|
||||
|
||||
assertTrue(a == b)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenUser_whenCheckReference_thenEqualReference() {
|
||||
val user = User("John", 30, listOf("Hiking, Chess"))
|
||||
val user2 = User("Sarah", 28, listOf("Shopping, Gymnastics"))
|
||||
|
||||
assertFalse(user === user2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenUser_whenCheckValue_thenStructurallyEqual() {
|
||||
val user = User("John", 30, listOf("Hiking, Chess"))
|
||||
val user2 = User("John", 30, listOf("Hiking, Chess"))
|
||||
|
||||
assertTrue(user == user2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenArray_whenCheckReference_thenEqualReference() {
|
||||
val hobbies = arrayOf("Riding motorcycle, Video games")
|
||||
val hobbies2 = arrayOf("Riding motorcycle, Video games")
|
||||
|
||||
assertFalse(hobbies === hobbies2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenArray_whenCheckContent_thenStructurallyEqual() {
|
||||
val hobbies = arrayOf("Hiking, Chess")
|
||||
val hobbies2 = arrayOf("Hiking, Chess")
|
||||
|
||||
assertTrue(hobbies contentEquals hobbies2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class PageTest {
|
||||
|
||||
private val page = PageImpl(1, 10, "Java", "Kotlin", "Scala")
|
||||
|
||||
@Test
|
||||
fun `Get convention should work as expected`() {
|
||||
assertEquals(page[1], "Kotlin")
|
||||
assertEquals(page[1, 3], listOf("Kotlin", "Scala"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `In convention should work on a page as expected`() {
|
||||
assertTrue("Kotlin" in page)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class PageImpl<T>(val page: Int, val size: Int, vararg val elements: T) : Page<T> {
|
||||
override fun pageNumber(): Int = page
|
||||
override fun pageSize(): Int = size
|
||||
override fun elements(): MutableList<T> = mutableListOf(*elements)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class PointTest {
|
||||
|
||||
private val p1 = Point(1, 2)
|
||||
private val p2 = Point(2, 3)
|
||||
|
||||
@Test
|
||||
fun `We should be able to add two points together using +`() {
|
||||
assertEquals(p1 + p2, Point(3, 5))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `We shoud be able to subtract one point from another using -`() {
|
||||
assertEquals(p1 - p2, Point(-1, -1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `We should be able to multiply two points together with *`() {
|
||||
assertEquals(p1 * p2, Point(2, 6))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `We should be able to divide one point by another`() {
|
||||
assertEquals(p1 / p2, Point(0, 0))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `We should be able to scale a point by an integral factor`() {
|
||||
assertEquals(p1 * 2, Point(2, 4))
|
||||
assertEquals(2 * p1, Point(2, 4))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `We should be able to add points to an empty shape`() {
|
||||
val line = shape {
|
||||
+Point(0, 0)
|
||||
+Point(1, 3)
|
||||
}
|
||||
|
||||
assertTrue(Point(0, 0) in line.points)
|
||||
assertTrue(Point(1, 3) in line.points)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.operators
|
||||
|
||||
import java.math.BigInteger
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class UtilsTest {
|
||||
|
||||
@Test
|
||||
fun `We should be able to add an int value to an existing BigInteger using +`() {
|
||||
assertEquals(BigInteger.ZERO + 1, BigInteger.ONE)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class CharRangeTest {
|
||||
|
||||
@Test
|
||||
fun testCharRange() {
|
||||
assertEquals(listOf('a', 'b', 'c'), ('a'..'c').toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCharDownRange() {
|
||||
assertEquals(listOf('c', 'b', 'a'), ('c'.downTo('a')).toList())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class ColorTest {
|
||||
|
||||
@Test
|
||||
fun testEnumRange() {
|
||||
|
||||
println(Color.values().toList());
|
||||
val red = Color.RED
|
||||
val yellow = Color.YELLOW
|
||||
val range = red..yellow
|
||||
|
||||
assertTrue { range.contains(Color.MAGENTA) }
|
||||
assertFalse { range.contains(Color.BLUE) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FilterTest {
|
||||
|
||||
val r = 1..10
|
||||
|
||||
@Test
|
||||
fun filterTest() {
|
||||
assertEquals(listOf(2, 4, 6, 8, 10), r.filter { it -> it % 2 == 0 }.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun mapTest() {
|
||||
assertEquals(listOf(1, 4, 9, 16, 25, 36, 49, 64, 81, 100), r.map { it -> it * it }.toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun reduceTest() {
|
||||
assertEquals(55, r.reduce { a, b -> a + b })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class FirstLastTest {
|
||||
|
||||
@Test
|
||||
fun testFirst() {
|
||||
assertEquals(1, (1..9).first)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLast() {
|
||||
assertEquals(9, (1..9).last)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStep() {
|
||||
assertEquals(2, (1..9 step 2).step)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class OtherRangeFunctionsTest {
|
||||
|
||||
val r = 1..20
|
||||
val repeated = listOf(1, 1, 2, 4, 4, 6, 10)
|
||||
|
||||
@Test
|
||||
fun testMin() {
|
||||
assertEquals(1, r.min())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMax() {
|
||||
assertEquals(20, r.max())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSum() {
|
||||
assertEquals(210, r.sum())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAverage() {
|
||||
assertEquals(10.5, r.average())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCount() {
|
||||
assertEquals(20, r.count())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDistinct() {
|
||||
assertEquals(listOf(1, 2, 4, 6, 10), repeated.distinct())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class RangeTest {
|
||||
|
||||
@Test
|
||||
fun testRange() {
|
||||
assertEquals(listOf(1,2,3), (1.rangeTo(3).toList()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDownTo(){
|
||||
assertEquals(listOf(3,2,1), (3.downTo(1).toList()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUntil(){
|
||||
assertEquals(listOf(1,2), (1.until(3).toList()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ReverseRangeTest {
|
||||
|
||||
@Test
|
||||
fun reversedTest() {
|
||||
assertEquals(listOf(9, 6, 3), (1..9).reversed().step(3).toList())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class StepTest {
|
||||
|
||||
@Test
|
||||
fun testStep() {
|
||||
assertEquals(listOf(1, 3, 5, 7, 9), (1..9 step 2).toList())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStepDown() {
|
||||
assertEquals(listOf(9, 7, 5, 3, 1), (9 downTo 1 step 2).toList())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.range
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class UntilRangeTest {
|
||||
|
||||
@Test
|
||||
fun testUntil() {
|
||||
assertEquals(listOf(1, 2, 3, 4), (1 until 5).toList())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.baeldung.rangeiterator
|
||||
|
||||
import org.junit.Test
|
||||
import java.lang.IllegalStateException
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class CustomColorTest {
|
||||
|
||||
@Test
|
||||
fun testInvalidConstructor(){
|
||||
assertFailsWith(IllegalStateException::class){
|
||||
CustomColor(-1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertHas10Colors(){
|
||||
assertTrue {
|
||||
val a = CustomColor(1)
|
||||
val b = CustomColor(10)
|
||||
val range = a..b
|
||||
for(cc in range){
|
||||
println(cc)
|
||||
}
|
||||
range.toList().size == 10
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun assertContains0xCCCCCC(){
|
||||
assertTrue {
|
||||
val a = CustomColor(0xBBBBBB)
|
||||
val b = CustomColor(0xDDDDDD)
|
||||
val range = a..b
|
||||
range.contains(CustomColor(0xCCCCCC))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.baeldung.trywithresource
|
||||
|
||||
import org.junit.Test
|
||||
import java.beans.ExceptionListener
|
||||
import java.beans.XMLEncoder
|
||||
import java.io.*
|
||||
import java.lang.Exception
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
class UseTest {
|
||||
|
||||
@Test
|
||||
fun givenCloseable_whenUseIsCalled_thenItIsClosed() {
|
||||
val stringWriter = StringWriter()
|
||||
val writer = BufferedWriter(stringWriter) //Using a BufferedWriter because after close() it throws.
|
||||
writer.use {
|
||||
assertEquals(writer, it)
|
||||
|
||||
it.write("something")
|
||||
}
|
||||
try {
|
||||
writer.write("something else")
|
||||
|
||||
fail("write() should have thrown an exception because the writer is closed.")
|
||||
} catch (e: IOException) {
|
||||
//Ok
|
||||
}
|
||||
|
||||
assertEquals("something", stringWriter.toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenAutoCloseable_whenUseIsCalled_thenItIsClosed() {
|
||||
val baos = ByteArrayOutputStream()
|
||||
val encoder = XMLEncoder(PrintStream(baos)) //XMLEncoder is AutoCloseable but not Closeable.
|
||||
//Here, we use a PrintStream because after close() it throws.
|
||||
encoder.exceptionListener = ThrowingExceptionListener()
|
||||
encoder.use {
|
||||
assertEquals(encoder, it)
|
||||
|
||||
it.writeObject("something")
|
||||
}
|
||||
try {
|
||||
encoder.writeObject("something else")
|
||||
encoder.flush()
|
||||
|
||||
fail("write() should have thrown an exception because the encoder is closed.")
|
||||
} catch (e: IOException) {
|
||||
//Ok
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenSimpleFormIsUsed_thenItWorks() {
|
||||
StringWriter().use { it.write("something") }
|
||||
}
|
||||
}
|
||||
|
||||
class ThrowingExceptionListener : ExceptionListener {
|
||||
override fun exceptionThrown(e: Exception?) {
|
||||
if(e != null) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.baeldung.voidtypes
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertNull
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class VoidTypesUnitTest {
|
||||
|
||||
// Un-commenting below methods will result into compilation error
|
||||
// as the syntax used is incorrect and is used for explanation in tutorial.
|
||||
|
||||
// fun returnTypeAsVoidAttempt1(): Void {
|
||||
// println("Trying with Void as return type")
|
||||
// }
|
||||
|
||||
// fun returnTypeAsVoidAttempt2(): Void {
|
||||
// println("Trying with Void as return type")
|
||||
// return null
|
||||
// }
|
||||
|
||||
fun returnTypeAsVoidSuccess(): Void? {
|
||||
println("Function can have Void as return type")
|
||||
return null
|
||||
}
|
||||
|
||||
fun unitReturnTypeForNonMeaningfulReturns(): Unit {
|
||||
println("No meaningful return")
|
||||
}
|
||||
|
||||
fun unitReturnTypeIsImplicit() {
|
||||
println("Unit Return type is implicit")
|
||||
}
|
||||
|
||||
fun alwaysThrowException(): Nothing {
|
||||
throw IllegalArgumentException()
|
||||
}
|
||||
|
||||
fun invokeANothingOnlyFunction() {
|
||||
alwaysThrowException()
|
||||
|
||||
var name = "Tom"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenJavaVoidFunction_thenMappedToKotlinUnit() {
|
||||
assertTrue(System.out.println() is Unit)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenVoidReturnType_thenReturnsNullOnly() {
|
||||
assertNull(returnTypeAsVoidSuccess())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() {
|
||||
assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() {
|
||||
assertTrue(unitReturnTypeIsImplicit() is Unit)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.baeldung.whenblock
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class WhenBlockUnitTest {
|
||||
|
||||
@Test
|
||||
fun testWhenExpression() {
|
||||
val directoryType = UnixFileType.D
|
||||
|
||||
val objectType = when (directoryType) {
|
||||
UnixFileType.D -> "d"
|
||||
UnixFileType.HYPHEN_MINUS -> "-"
|
||||
UnixFileType.L -> "l"
|
||||
}
|
||||
|
||||
assertEquals("d", objectType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWhenExpressionWithDefaultCase() {
|
||||
val fileType = UnixFileType.L
|
||||
|
||||
val result = when (fileType) {
|
||||
UnixFileType.L -> "linking to another file"
|
||||
else -> "not a link"
|
||||
}
|
||||
|
||||
assertEquals("linking to another file", result)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun testWhenExpressionWithThrowException() {
|
||||
val fileType = UnixFileType.L
|
||||
|
||||
val result: Boolean = when (fileType) {
|
||||
UnixFileType.HYPHEN_MINUS -> true
|
||||
else -> throw IllegalArgumentException("Wrong type of file")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWhenStatement() {
|
||||
val fileType = UnixFileType.HYPHEN_MINUS
|
||||
|
||||
when (fileType) {
|
||||
UnixFileType.HYPHEN_MINUS -> println("Regular file type")
|
||||
UnixFileType.D -> println("Directory file type")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCaseCombination() {
|
||||
val fileType = UnixFileType.D
|
||||
|
||||
val frequentFileType: Boolean = when (fileType) {
|
||||
UnixFileType.HYPHEN_MINUS, UnixFileType.D -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
assertTrue(frequentFileType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWhenWithoutArgument() {
|
||||
val fileType = UnixFileType.L
|
||||
|
||||
val objectType = when {
|
||||
fileType === UnixFileType.L -> "l"
|
||||
fileType === UnixFileType.HYPHEN_MINUS -> "-"
|
||||
fileType === UnixFileType.D -> "d"
|
||||
else -> "unknown file type"
|
||||
}
|
||||
|
||||
assertEquals("l", objectType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDynamicCaseExpression() {
|
||||
val unixFile = UnixFile.SymbolicLink(UnixFile.RegularFile("Content"))
|
||||
|
||||
when {
|
||||
unixFile.getFileType() == UnixFileType.D -> println("It's a directory!")
|
||||
unixFile.getFileType() == UnixFileType.HYPHEN_MINUS -> println("It's a regular file!")
|
||||
unixFile.getFileType() == UnixFileType.L -> println("It's a soft link!")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCollectionCaseExpressions() {
|
||||
val regularFile = UnixFile.RegularFile("Test Content")
|
||||
val symbolicLink = UnixFile.SymbolicLink(regularFile)
|
||||
val directory = UnixFile.Directory(listOf(regularFile, symbolicLink))
|
||||
|
||||
val isRegularFileInDirectory = when (regularFile) {
|
||||
in directory.children -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val isSymbolicLinkInDirectory = when {
|
||||
symbolicLink in directory.children -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
assertTrue(isRegularFileInDirectory)
|
||||
assertTrue(isSymbolicLinkInDirectory)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRangeCaseExpressions() {
|
||||
val fileType = UnixFileType.HYPHEN_MINUS
|
||||
|
||||
val isCorrectType = when (fileType) {
|
||||
in UnixFileType.D..UnixFileType.L -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
assertTrue(isCorrectType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testWhenWithIsOperatorWithSmartCase() {
|
||||
val unixFile: UnixFile = UnixFile.RegularFile("Test Content")
|
||||
|
||||
val result = when (unixFile) {
|
||||
is UnixFile.RegularFile -> unixFile.content
|
||||
is UnixFile.Directory -> unixFile.children.map { it.getFileType() }.joinToString(", ")
|
||||
is UnixFile.SymbolicLink -> unixFile.originalFile.getFileType()
|
||||
}
|
||||
|
||||
assertEquals("Test Content", result)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
<modules>
|
||||
<module>core-kotlin-annotations</module>
|
||||
<module>core-kotlin-io</module>
|
||||
<module>core-kotlin-lang</module>
|
||||
<module>core-kotlin-lang-2</module>
|
||||
<module>core-kotlin-strings</module>
|
||||
</modules>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user