[BAEL-19883] - Move articles out of core-kotlin part2

This commit is contained in:
catalin-burcea
2019-12-16 16:26:38 +02:00
parent 2e1d1ffb01
commit b34da5aea9
58 changed files with 85 additions and 41 deletions

View 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)

View 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>

View File

@@ -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;
}
}

View File

@@ -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
}

View File

@@ -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);
}
}

View File

@@ -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])
}
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,8 @@
package com.baeldung.constant
class TestKotlinConstantClass {
companion object {
const val COMPANION_OBJECT_NUMBER = 40
}
}

View File

@@ -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;
}
}

View File

@@ -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)
}
}

View File

@@ -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);
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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?)

View File

@@ -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)
}
}

View 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)

View 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>

View File

@@ -0,0 +1,3 @@
package com.baeldung.destructuringdeclarations
data class Person(var id: Int, var name: String, var age: Int)

View File

@@ -0,0 +1,3 @@
package com.baeldung.destructuringdeclarations
data class Result(val result: Int, val status: String)

View File

@@ -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!" }
}

View File

@@ -0,0 +1,3 @@
package com.baeldung.equalityoperators
data class User(val name: String, val age: Int, val hobbies: List<String>)

View File

@@ -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()
}

View File

@@ -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()

View File

@@ -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
}
}

View File

@@ -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()

View File

@@ -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
}

View File

@@ -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"))

View File

@@ -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)
}
}

View File

@@ -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))
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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())
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,8 @@
package com.baeldung.range
fun main(args: Array<String>) {
for (i in 1 until 9) {
print(i)
}
}

View File

@@ -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)
}
}

View File

@@ -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
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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())
}
}

View File

@@ -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) }
}
}

View File

@@ -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 })
}
}

View File

@@ -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)
}
}

View File

@@ -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())
}
}

View File

@@ -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()))
}
}

View File

@@ -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())
}
}

View File

@@ -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())
}
}

View File

@@ -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())
}
}

View File

@@ -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))
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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>