Created
December 18, 2021 01:38
-
-
Save claraj/22f5b88ab49edce928f647368c387664 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlin.random.Random | |
/****** Number types, Int and Double ******/ | |
val classCredits = 6 // A constant Int value | |
val classWeeks: Int = 17 // Can include type | |
val classHours = 2.5 // A constant Double value | |
val textbookPrice: Double = 35.99 // constant Double, can include type | |
var studentsRegistered = 5 // Int variable | |
// Math works as you expect | |
// another student registered! | |
studentsRegistered = studentsRegistered + 1 | |
// and another one! | |
studentsRegistered =+ 1 | |
// and another one! | |
studentsRegistered++ | |
// someone dropped | |
studentsRegistered-- | |
val totalClassTime = classWeeks * classHours | |
/****** Booleans ******/ | |
val isThisTheAndroidClass = true // boolean constant | |
val usingJava = false // boolean constant | |
val usingKotlin: Boolean = true // include type if you like | |
var nightMode = true // a variable, we can change | |
// now it's daytime | |
nightMode = false | |
var gameOver: Boolean = false // can include type if you like | |
// to do ... play game ... | |
gameOver = true | |
/****** Strings ******/ | |
val className = "Android Application Development" // String constant | |
val deliveryMethod: String = "Online Synchronous" | |
var androidVersion = "Jelly Bean" // a String variable | |
// time to upgrade | |
androidVersion = "Snow Cone" // Or 12, if you prefer the official name | |
// Escape characters are as expected | |
val message = "The code name for Android 12 is \"Snow Cone\" and it was \nreleased on October 12, 2021." | |
println(message) | |
//The code name for Android 12 is "Snow Cone" and it was | |
//released on October 12, 2021. | |
// String library methods do the same tasks you expect | |
println(message.length) | |
println(message.contains("Android")) // True | |
println(message.lowercase()) | |
println(message.uppercase()) | |
// Can use == to compare strings, === to compare objects. No need to use .equals | |
if (androidVersion == "Snow Cone") { | |
println("You are running the latest version of Android") // It's December 2021 so this may be out of date :) | |
} | |
if (androidVersion.equals("snow cone", ignoreCase = true)) { | |
println("You are running the latest version of Android") // It's December 2021 so this may be out of date :) | |
} | |
// Template strings, string interpolation | |
// So easy! | |
// The textbook for the Android Application Development class costs 35.99 | |
println("The textbook for the $className class costs $textbookPrice") | |
// What if you need a $ in a string? Just include one, if it's not | |
// followed by a variable it will be interpreted as a $ | |
println("The textbook for the $className class costs $$textbookPrice") | |
println("Here's a $ symbol") | |
// Can also write expressions, include { } | |
// "There are 31 letters in Android Application Development" | |
println("There are ${className.length} letters in $className") | |
/****** Comments ******/ | |
// A single line comment | |
/* A multi | |
line | |
comment | |
*/ | |
/** A documentation comment | |
* which can have multiple lines */ | |
/****** Conditional Code, if statements ******/ | |
val secretPassword = "kittens" | |
if (secretPassword.length < 8) { | |
println("This is not a good password") | |
} else { | |
println("This may be a good password") | |
} | |
val androidVersionNumber = 12 | |
if (androidVersionNumber >= 12) { | |
println("You are running Snow Cone or later") | |
} else if (androidVersionNumber >= 10) { | |
println("You are running Pie or later") | |
} else { | |
println("You are running an earlier version than Pie") | |
} | |
// Alternative to if, else if, else statements | |
// Other languages have switch statements | |
when { | |
androidVersionNumber >= 12 -> { | |
println("You are running Snow Cone or later") | |
} | |
androidVersionNumber >= 9 -> { | |
println("You are running Pie or later") | |
} | |
else -> { | |
println("You are running an earlier version than Pie") | |
} | |
} | |
// When with exact matches | |
when (androidVersionNumber) { | |
12 -> println("You are running Snow Cone or later") | |
11 -> println("Android 11 doesn't have a code name") | |
10 -> println("You are running Pie or later") | |
else -> println("You are running an earlier version than Pie") | |
} | |
// When as an expression | |
val codeName = when(androidVersionNumber) { | |
12 -> "Snow Cone" | |
11 -> "R" | |
10 -> "Q" | |
9 -> "Pie" | |
8 -> "Oreo" | |
else -> "An earlier version of Android" | |
} | |
// Testing for equality | |
// Strings can be compared with == and you probably want to use == most of the time. | |
val aaa1 = "aaa" | |
(aaa1 == "aaa") // true, a .equals check | |
(aaa1 === aaa1) // true, same object | |
val a = 'a' | |
val aaa2 = "aa$a" // Also the characters "aaa" but a different object | |
(aaa1 == aaa2) // true, uses .equals() check | |
(aaa1 === aaa2) // FALSE - do not refer to the same String object | |
// Case-insensitive comparisons | |
("aaa".equals("AAA", ignoreCase = true) ) // True | |
/***** For Loops *******/ | |
for (i in 0..5) { // 0 to 5, including 5 | |
println(i) | |
} | |
for (i in 0 until 5) { // 0 to 4 | |
println(i) | |
} | |
/***** While Loops ******/ | |
var greeting = "hello" | |
while (greeting.length < 50) { | |
greeting += "!" | |
} | |
print(greeting) // hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | |
val secretNumber = 3 | |
var numberOfGuesses = 0 | |
do { | |
val guess = Random.nextInt(0, 5) | |
numberOfGuesses++ | |
} while (secretNumber != guess) | |
println("The secret number was guessed in $numberOfGuesses random guesses") | |
/****** Functions ******/ | |
fun addExclamationPoints(message: String, number: Int): String { | |
var outputMessage = message | |
for (n in 0 until number) { | |
outputMessage += 1 | |
} | |
return outputMessage | |
} | |
println(addExclamationPoints("Hello", 5)) // Hello!!!!! | |
fun shout(message: String) { // No return type | |
println(message.uppercase()) | |
} | |
shout("hello android") // HELLO ANDROID | |
fun greeting(name: String, arriving: Boolean = true): String { | |
if (arriving) { | |
return "Welcome, $name, nice to meet you!" | |
} else { | |
return "Goodbye $name, hope to see you again soon!" | |
} | |
} | |
println(greeting("Alice")) // "Welcome, Alice, nice to meet you!" | |
println(greeting("Alice", true)) // "Welcome, Alice, nice to meet you!" | |
println(greeting("Alice", false)) // "Goodbye Alice, hope to see you again soon!" | |
/***** Lists *****/ | |
// This list can't be modified | |
val androidVersions = listOf( | |
"Cupcake", | |
"Donut", | |
"Eclair", | |
"Froyo", | |
"Gingerbread", | |
"Honeycomb", | |
"Ice Cream Sandwich", | |
"Jelly Bean", | |
"Kitkat", | |
"Lollipop", | |
"Marshmallow") | |
// access by index with [] | |
println(androidVersions[3]) // Froyo | |
// Library functions | |
println(androidVersions.first()) // Cupcake | |
println(androidVersions.firstOrNull()) // null, if the list is empty | |
println(androidVersions.last()) // Marshmallow | |
println(androidVersions.lastOrNull()) // Returns null if list is empty | |
println(androidVersions.size) // Size is a property, 4 | |
println(androidVersions.contains("Pie")) // false | |
println(androidVersions.indexOf("Jelly Bean")) // 8 | |
println(androidVersions.isEmpty()) // false | |
// Functional tasks - map, filter | |
val shortNames = androidVersions.filter { a -> (a.length < 6) } | |
println(shortNames) | |
// [Donut, Froyo] | |
val longNames = androidVersions.filter { it.length > 10 } // Variation with default parameter name it | |
println(longNames) | |
// [Gingerbread, Ice Cream Sandwich, Marshmallow] | |
val uppercaseNames = androidVersions.map { a -> a.uppercase() } | |
println(uppercaseNames) | |
// [CUPCAKE, DONUT, ECLAIR, FROYO, GINGERBREAD, HONEYCOMB, ICE CREAM SANDWICH, JELLY BEAN, KITKAT, LOLLIPOP, MARSHMALLOW] | |
val lowercaseNames = androidVersions.map { it.lowercase() } | |
println(lowercaseNames) | |
// [cupcake, donut, eclair, froyo, gingerbread, honeycomb, ice cream sandwich, jelly bean, kitkat, lollipop, marshmallow] | |
// Want to add, edit, or remove elements? Make a MutableList | |
val flowers = mutableListOf("Rose", "Daisy", "Orchid", "Dandelion", "Lilac") | |
flowers.add("Sunflower") // [Rose, Daisy, Orchid, Dandelion, Lilac, Sunflower] | |
flowers[1] = "Poppy" // Modify, use []. [Rose, Poppy, Orchid, Dandelion, Lilac, Sunflower] | |
flowers.remove("Dandelion") // [Rose, Poppy, Orchid, Lilac, Sunflower] | |
val twoLessFlowers = flowers.drop(2) // remove first n elements, and return a new list | |
println(twoLessFlowers) // [Orchid, Dandelion, Lilac] | |
println(flowers) // Not modified, [Rose, Poppy, Orchid, Lilac, Sunflower] | |
val removeLastThree = flowers.dropLast(3) // [Rose, Poppy] | |
val sortedFlowers = flowers.sorted() // Returns a new list, does not sort in place | |
/***** Maps ******/ | |
// Create a map that can't be changed | |
// Keys should all be one type, values should all be the same type | |
// Keys don't need to be the same type as values. Keys are often String or Int | |
val stateAbbreviations = mapOf( "Michigan" to "MI", "Minnesota" to "MN", "Wisconsin" to "WI") | |
val bookPrices = mapOf("Automate the Boring Stuff" to 0.0, "Big Nerd Ranch" to 35.99, "SQL" to 54.99) | |
// Can work with keys, and values | |
val stateNames = stateAbbreviations.keys | |
println(bookPrices.values.sum()) // 90.98 | |
// Iterate over map | |
for ( (state, abbreviation) in stateAbbreviations ) { | |
println("The abbreviations for $state is $abbreviation") | |
} | |
// Read value for a key. Returns null if not found | |
val michiganAbbreviation = stateAbbreviations["Michigan"] | |
val wisconsinAbbreviation = stateAbbreviations.get("Wisconsin") // Alternative get method | |
println("The abbreviation for Minnesota is ${stateAbbreviations["Minnesota"]}") | |
println("The abbreviation for Iowa is ${stateAbbreviations["Iowa"]}") // null | |
println("Do we have a record for Montana? ${stateAbbreviations.containsKey("Montana")}") | |
// Get default value | |
val californiaAbbreviation = stateAbbreviations.getOrDefault("California", "Not Found") | |
// Create mutable maps if necessary to add/remove key-value pairs, or edit the value for a key | |
val abbreviationsStates = mutableMapOf("MI" to "Michigan", "MN" to "Minnesota", "WI" to "Wisconsin") | |
// Can add new key-value pairs | |
abbreviationsStates["IA"] = "Iowa" | |
abbreviationsStates["MT"] = "Vermont" // Oops, a typo | |
// Same syntax to edit key-value pairs | |
abbreviationsStates["MT"] = "Montana" // Fixed it | |
val vermontAbbr = "VT" | |
val vermontName = "Vermont" | |
abbreviationsStates[vermontAbbr] = vermontName // Variables work just as well | |
println(abbreviationsStates) // {MI=Michigan, MN=Minnesota, WI=Wisconsin, IA=Iowa, MT=Montana, VT=Vermont} | |
// Removing key-value pairs - Sorry Iowa | |
abbreviationsStates.remove("IA") // {MI=Michigan, MN=Minnesota, WI=Wisconsin, MT=Montana, VT=Vermont} | |
/*** Lambdas and Predicates ****/ | |
// Create a lambda function - the full version | |
val lessThanSix1: (String) -> Boolean = { name: String -> name.length < 6 } | |
val shortNames1 = androidVersions.filter(lessThanSix1) | |
// Can omit types within the lambda if they can be inferred | |
val lessThanSix2: (String) -> Boolean = { name -> name.length < 6 } | |
val shortNames2 = androidVersions.filter(lessThanSix2) | |
// Can omit types in the definition if they can be inferred | |
val lessThanSix3 = { name:String -> name.length < 6 } | |
val shortNames3 = androidVersions.filter(lessThanSix3) | |
val shortNames4 = androidVersions.filter( { name: String -> name.length < 6 } ) | |
val shortNames5 = androidVersions.filter( { name -> name.length < 6 } ) // Can infer return type | |
val shortNames6 = androidVersions.filter() { name -> name.length < 6 } // Kotlin prefers trailing lambda | |
val shortNames7 = androidVersions.filter { name -> name.length < 6 } // If the lambda is the only argument, can omit the () | |
val shortNames8 = androidVersions.filter { it -> it.length < 6 } // If the lambda only has one argument, assume it's called it... | |
val shortNames9 = androidVersions.filter { it.length < 6 } // ...Then can omit the argument, implicit it... | |
/***** Handling null values ******/ | |
var flower = "Poppy" | |
//flower = null // Not allowed, compile error | |
println(flower.length) // A NPE can never occur, null-safe call | |
var tree: String? = "Pine" // Have to specify that a value may be null | |
tree = null // allowed | |
//println(tree.length) // Compile error since tree can be null | |
println(tree?.length) // null-safety operator. Returns null | |
println(tree ?: "Sorry, there is no tree.") // Elvis operator. If LHS is null, use RHS | |
println(tree?.length ?: "Unable to count letters.") // Elvis operator. If LHS is null, use RHS | |
//println(tree!!.length) // non-null assertion operator. Throw a NPE if tree is null. Rare to use this | |
if (tree == null) { | |
println("Unable to count letters") | |
} else { | |
println(tree!!.length) | |
// This is probably not going to throw a NPE but it's cleaner to use ? or ?: | |
} | |
val stringsWithNull = listOf("a", "b", null, "c") // NullableList of String? values | |
for (s in stringsWithNull) { | |
// println(s.length) // not ok - will raise a NullPointerException so compiler won't allow | |
println(s?.length) // null, if s is null | |
println(s ?: "This string is null so has no length") // The Elvis operator | |
} | |
val getRidOfNull = stringsWithNull.filterNotNull() // no nulls here, list of String not String? | |
for (s in getRidOfNull) { | |
println(s.length) // OK - no nulls here | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment