SlideShare a Scribd company logo
From Java to Kotlin beyond
Alt+Shift+Cmd+K
Fabio Collini
@fabioCollini
linkedin.com/in/fabiocollini
github.com/fabioCollini
medium.com/@fabioCollini
codingjam.it
Android programmazione avanzata
Android Developers Italia
Ego slide
Kotlin can be configured in one click
A Java class can be converted easily
ok, now what?
LAMB
DAS
DATACLASSES
COLLE
CTIONS
ASYNC
CODE
DELE
GATES
Agenda
LAMB
DAS
JavaCode KotlinCode
/**
* Returns the first element matching the given [predicate].
* @throws [NoSuchElementException] if no such element is found.
*/
inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {
for (element in this) {
if (predicate(element)) {
return element
}1
}2
throw NoSuchElementException(
"Collection contains no element matching the predicate.")
}3
val list = listOf("Java", "Kotlin")
val s = list.first({_v: String ->
v.length > 4
_})
val list = listOf("Java", "Kotlin")
val s = list.first({_v ->
v.length > 4
_})
val list = listOf("Java", "Kotlin")
val s = list.first({_
it.length > 4
_})
val list = listOf("Java", "Kotlin")
val s = list.first {_
it.length > 4
_}
val list = listOf("Java", "Kotlin")
val s = list.first { it.length > 4_}
public static <T> T first(Iterable<T> list, Predicate<T> predicate) {_
for (T t : list) {__
if (predicate.test(t)) {___
return t;
}____
}_____
throw new NoSuchElementException(
"Collection contains no element matching the predicate.");
}______
inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {_
for (element in this) {__
if (predicate(element)) {___
return element
}____
}____
throw NoSuchElementException(
"Collection contains no element matching the predicate.")
}_____
List<String> list = Arrays.asList("Java", “Kotlin");
String s = first(list, p -> p.length() > 4);
List<String> list = Arrays.asList("Java", “Kotlin");
String s = first(list, p -> p.length() > 4);
val list = listOf("Java", "Kotlin")
val s = list.first { it.length > 4 }
From java to kotlin beyond alt+shift+cmd+k
inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {
for (element in this) {
if (predicate(element)) {
return element
}
}
throw NoSuchElementException(
"Collection contains no element matching the predicate.")
}
public static <T> T first(List<T> list, Predicate<T> predicate) {
for (T t : list) {
if (predicate.test(t)) {
return t;
}
}
throw new NoSuchElementException(
“Collection contains no element matching the predicate.");
}
inline
val list = listOf("Java", "Kotlin")
val s = list.first { it.length > 4 }
inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {
for (element in this) {
if (predicate(element)) {
return element
}
}
throw NoSuchElementException(
"Collection contains no element matching the predicate.")
}
val list = listOf("Java", "Kotlin")
var ret: String? = null
for (element in list) {
if (element.length > 4) {
ret = element;
break
}
}
if (ret == null)
throw NoSuchElementException(
"Collection contains no element matching the predicate.")
val s = ret
DATACLASSES
class Person(var name:_String)_
public class Person {
private String name;
public Person(String name) {
this.name = name;
}1
public String getName() {
return name;
}2
public void setName(String name) {
this.name = name;
}3
}4
public class Person {
private long id;
private String name;
private int age;
public Person(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public long getId()_{_return id;_}
public String getName()_{_return name;_}
public int getAge()_{_return age;_}
}4
class Person(
val id: Long,
val name: String,
val age: Int
)_
@Parcelize
data class Person(
val id: Long,
val name: String,
val age: Int
)_: Parcelable
public class Person implements Parcelable {
private long id;
private String name;
private int age;
public Person(long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}1
protected Person(Parcel in) {
id = in.readLong();
name = in.readString();
age = in.readInt();
}2
public long getId()_{_return id;_}
public String getName()_{_return name;_}
public int getAge()_{_return age;_}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person that = (Person) o;
if (id != that.id) return false;
if (age != that.age) return false;
return name != null ? name.equals(that.name) : that.name == null;
}3
@Override public int hashCode() {
int result = (int) (id ^ (id >>> 32));
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + age;
return result;
}4
@Override public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + ''' +
", age=" + age +
'}';
}5
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(id);
dest.writeString(name);
dest.writeInt(age);
}6
@Override
public int describeContents() {
return 0;
}7
public static final Creator<Person> CREATOR = new Creator<Person>() {
@Override
public Person createFromParcel(Parcel in) {
return new Person(in);
}8
@Override
public Person[] newArray(int size) {
return new Person[size];
}9
};
}_
@AutoValue
public abstract class Person
implements Parcelable {_
public static Person create(
long id, String name, int age) {
return new AutoValue_Person(
id, name, age);
}__
public abstract long id();
public abstract String name();
public abstract int age();
public abstract Person withName(String name);
}_
@Parcelize
data class Person(
val id: Long,
val name: String,
val age: Int
)_: Parcelable
val p = Person(1, "name", 10)
val p1 = p.copy(name = "newName", age = 20)_
Person p = Person.create(1, "name", 10);
Person p1 = p.withName("newName");
val p = Person(1, "name", 10)
val (_, name, age) = p
println("$name $age")
data class Pair<out A, out B>(
val first: A,
val second: B
) : Serializable {
override fun toString(): String = "($first, $second)"
}_
data class Pair<out A, out B>(
val first: A,
val second: B
) : Serializable {
override fun toString(): String = "($first, $second)"
}_
val myPair: Pair<Int, Int> = Pair(10, 20)
val otherPair: Pair<Int, Int> = 10 to 20
infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
fun myMethod(): Pair<Int, Int> {
//...
return 10 to 20
}
val (a, b) = myMethod()
COLLE
CTIONS
System.out.println(b.toString());
List<Person> people = Arrays.asList(...);
StringBuilder b = new StringBuilder();
for (String s : cities) {
if (b.length() > 0) {
b.append(", ");
}3
b.append(s);
}4
for (Person person : people) {
City city = person.getAddress().getCity();
if (city.getRegion().equals("Tuscany")) {
cities.add(city.getName() + " (" + city.getCode() + ")");
}1
}2
Set<String> cities = new TreeSet<>();
val people = listOf(...)
val s = people
.map { it.address.city }
.filter { it.region == "Tuscany" }
.distinct()
.sortedBy { it.name }
.joinToString { "${it.name} (${it.code})" }
println(s)
From java to kotlin beyond alt+shift+cmd+k
String s = Stream.of(people)
.map(it -> it.getAddress().getCity())
.filter(it -> it.getRegion().equals("Tuscany"))
.distinct()
.sortBy(City::getName)
.map(it -> it.getName() + " (" + it.getCode() + ")")
.collect(Collectors.joining(", "));
System.out.println(s);
val people = listOf(...)
val s = people
.asSequence()
.map { it.address.city }
.map { "${it.name} (${it.code})" }
.first { it.region == "Tuscany" }
println(s)
val youngest = people.minBy { it.age }
val peopleByCity: Map<City, List<Person>> =
people.groupBy { it.address.city }
val all: Boolean = people.all {
it.address.city.name == "Florence"
}1
val any: Boolean = people.any {
it.address.city.name == "Florence"
}2
val (adults: List<Person>, minors: List<Person>) =
people.partition { it.age >= 18 }
val readOnlyList: List<Int> = listOf(10, 20, 30)
val secondElement = readOnlyList[1]
val mutableList: MutableList<Int> = mutableListOf(10, 20, 30)
mutableList[1] = 21
val map = mapOf(1 to "ABC", 2 to "DEF")
val abc = map[1]
val mutableMap = mutableMapOf(1 to "ABC", 2 to "DEF")
mutableMap[3] = "XYZ"
val otherList = (mutableList - readOnlyList) + mutableMap.keys
ASYNC
CODE
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.text)
myTextView.text = "Loading..."
Thread.sleep(2000)
myTextView.text = "Loading something else..."
Thread.sleep(2000)
myTextView.text = "Done"
}_
/**
* Delays coroutine for a given time without blocking
* a thread and resumes it after a specified time.
* ...
*/
suspend fun delay(time: Long, unit: TimeUnit = MILLISECONDS) {
//...
}
suspend
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val myTextView = findViewById<TextView>(R.id.text)
async(UI) {
myTextView.text = "Loading..."
delay(2000)
myTextView.text = "Loading something else..."
delay(2000)
myTextView.text = "Done"
}async
}end
interface StackOverflowService {
@GET("/users")
fun getTopUsers(): Deferred<List<User>>
}A
async(UI) {
try {
val topUsers = service.getTopUsers().await()
val usersUi = topUsers.map { createUserUi(it) }
showInUi(usersUi)
} catch (e: Exception) {
showError(e)
}__
}___
interface MyService {
fun login(): Deferred<String>
fun loadData(token: String): Deferred<Data>
}A
async(UI) {
try {
val token = service.login().await()
val data = service.loadData(token).await()
showInUi(data)
} catch (e: Exception) {
showError(e)
}__
}___
service.login()
.flatMap { service.loadData(it) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ data -> showInUi(data) },
{ showError(it) }
)end
RxJavaCoroutines
async(UI) {
try {
val token = service.login().await()
val data = service.loadData(token).await()
showInUi(data)
} catch (e: Exception) {
showError(e)
}__
}___
RxJava
Coroutines
OR
RxJava
Coroutines
AND
RxJava Coroutines->
RxJavaCoroutines ->
rxCompletable, rxMaybe, rxSingle, rxObservable, rxFlowable
CompletableSource.await, MaybeSource.await, MaybeSource.awaitOrDefault,
MaybeSource.openSubscription, SingleSource.await,
ObservableSource.awaitFirst, ObservableSource.awaitFirstOrDefault,
ObservableSource.awaitFirstOrElse, ObservableSource.awaitFirstOrNull,
ObservableSource.awaitLast, ObservableSource.awaitSingle,
ObservableSource.openSubscription, ObservableSource.iterator
github.com/Kotlin/kotlinx.coroutines/tree/master/reactive/kotlinx-coroutines-rx2
My 2 cents
Suspending methods are easier to
use than RxJava Singles
Observables/Flowables are the best
abstraction for a stream of data
async(UI) {
try {
val token = service.login().await()
val data = service.loadData(token).await()
showInUi(data)
} catch (e: Exception) {
showError(e)
}__
}___
async(UI) {
try {
val token = service.login().await()
val data = service.loadData(token).await()
val otherData = service.loadOtherData(token).await()
showInUi(data, otherData)
} catch (e: Exception) {
showError(e)
}__
}___
async(UI) {
try {
val token = service.login().await()
val data = service.loadData(token)
val otherData = service.loadOtherData(token)
showInUi(data.await(), otherData.await())
} catch (e: Exception) {
showError(e)
}__
}___
async(UI) {
try {
val token = service.login().await()
updateProgress()
val data = service.loadData(token)
val otherData = service.loadOtherData(token)
showInUi(data.await(), otherData.await())
} catch (e: Exception) {
showError(e)
}__
}___
async(UI) {
try {
withTimeout(10, SECONDS) {
val token = retry(3) {
service.login().await()
}T
updateProgress()
val data = service.loadData(token)
val otherData = service.loadOtherData(token)
showInUi(data.await(), otherData.await())
}B
} catch (e: Exception) {
showError(e)
}__
}___
async(UI) {
try {
withTimeout(10, SECONDS) {
val token = retry(3) {
service.login().await()
}T
updateProgress()
val data = service.loadData(token)
val otherData = service.loadOtherData(token)
showInUi(data.await(), otherData.await())
}B
} catch (e: Exception) {
showError(e)
}__
}___
suspend fun <T> retry(times: Int, block: suspend () -> T): T {
repeat(times - 1) {
try {
return block()
} catch (ignored: Exception) {
}
}
return block()
}
DELE
GATES
class TokenHolder {0
var token = ""
}1
class TokenHolder(val prefs: SharedPreferences) {0
var token = ""
}1
class TokenHolder(val prefs: SharedPreferences) {
var token
get() = prefs.getString("token", "")
set(value) = prefs.edit().putString("token", value).apply()
}1
class TokenHolder(prefs: SharedPreferences) {
var token by prefs.string()
}1
class TokenHolder(prefs: SharedPreferences) {
var token by prefs.string()
}1
fun SharedPreferences.string(
defaultValue: String = "",
key: String? = null
): ReadWriteProperty<Any, String> {
return object : ReadWriteProperty<Any, String> {
override fun getValue(thisRef: Any, property: KProperty<*>): String {
return getString(key ?: property.name, defaultValue)
}2
override fun setValue(thisRef: Any, property: KProperty<*>,
value: String) {
edit().putString(key ?: property.name, value).apply()
}3
}4
}5
class TokenHolder(prefs: SharedPreferences) {
var token by prefs.string()
}1
tokenHolder.token += "ABC"
prefs.edit().putString(
"token",
prefs.getString("token", "") + "ABC"
).apply()
Wrapping up
inline methods to avoid extra classes
functional code is natural in Kotlin
code can be simplified using data
classes, coroutines and delegates
Links
AutoValue
https://github.com/google/auto/blob/master/value/userguide/index.md
Lightweight Stream
https://github.com/aNNiMON/Lightweight-Stream-API
Guide to kotlinx.coroutines by example
https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md
Kotlin coroutines, a deeper look
https://medium.com/@elizarov/kotlin-coroutines-a-deeper-look-180536305c3f
Kotlin delegates in Android development - part 1
https://hackernoon.com/kotlin-delegates-in-android-development-part-1-50346cf4aed7
Kotlin delegates in Android development - part 2
https://proandroiddev.com/kotlin-delegates-in-android-development-part-2-2c15c11ff438
THANKS
FOR YOUR
ATTENTION
QUESTIONS?
Android Developers Italia
androiddevs.it

More Related Content

PDF
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
PPTX
Poor Man's Functional Programming
PDF
Refactoring to Macros with Clojure
PDF
JDD 2016 - Pawel Byszewski - Kotlin, why?
PDF
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
PPTX
Kotlin collections
ODP
WorkingWithSlick2.1.0
PDF
Sneaking inside Kotlin features
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Poor Man's Functional Programming
Refactoring to Macros with Clojure
JDD 2016 - Pawel Byszewski - Kotlin, why?
TDC218SP | Trilha Kotlin - DSLs in a Kotlin Way
Kotlin collections
WorkingWithSlick2.1.0
Sneaking inside Kotlin features

What's hot (18)

PPTX
Kotlin standard
PDF
2014-11-01 01 Денис Нелюбин. О сортах кофе
PDF
Kotlin, why?
PDF
The Ring programming language version 1.5.2 book - Part 32 of 181
PPSX
Tuga it 2016 - What's New In C# 6
PDF
Feel of Kotlin (Berlin JUG 16 Apr 2015)
PDF
Idiomatic Kotlin
PDF
Nik Graf - Get started with Reason and ReasonReact
PPSX
What's new in C# 6 - NetPonto Porto 20160116
PDF
JAVA 8 : Migration et enjeux stratégiques en entreprise
PDF
Functional Scala 2020
PDF
Pragmatic Real-World Scala (short version)
PDF
The Ring programming language version 1.4 book - Part 9 of 30
PDF
Privet Kotlin (Windy City DevFest)
PDF
The Ring programming language version 1.6 book - Part 35 of 189
PDF
The Ring programming language version 1.9 book - Part 41 of 210
PDF
The Ring programming language version 1.2 book - Part 22 of 84
Kotlin standard
2014-11-01 01 Денис Нелюбин. О сортах кофе
Kotlin, why?
The Ring programming language version 1.5.2 book - Part 32 of 181
Tuga it 2016 - What's New In C# 6
Feel of Kotlin (Berlin JUG 16 Apr 2015)
Idiomatic Kotlin
Nik Graf - Get started with Reason and ReasonReact
What's new in C# 6 - NetPonto Porto 20160116
JAVA 8 : Migration et enjeux stratégiques en entreprise
Functional Scala 2020
Pragmatic Real-World Scala (short version)
The Ring programming language version 1.4 book - Part 9 of 30
Privet Kotlin (Windy City DevFest)
The Ring programming language version 1.6 book - Part 35 of 189
The Ring programming language version 1.9 book - Part 41 of 210
The Ring programming language version 1.2 book - Part 22 of 84
Ad

Similar to From java to kotlin beyond alt+shift+cmd+k (20)

PDF
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
PDF
No excuses, switch to kotlin
PDF
かとうの Kotlin 講座 こってり版
PPTX
Kotlin : Happy Development
PDF
Kotlin Data Model
PDF
Kotlin for Android Developers
PDF
Pure kotlin
PPTX
PDF
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
PDF
PDF
Scala collections api expressivity and brevity upgrade from java
PDF
Miracle of std lib
PDF
A quick and fast intro to Kotlin
PPTX
Kotlin is charming; The reasons Java engineers should start Kotlin.
PPTX
K is for Kotlin
PDF
Having Fun with Kotlin Android - DILo Surabaya
PDF
Introduction to Kotlin
PPTX
Kotlin Collections
PDF
Effective Java and Kotlin
PDF
Scala for Java Developers (Silicon Valley Code Camp 13)
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
No excuses, switch to kotlin
かとうの Kotlin 講座 こってり版
Kotlin : Happy Development
Kotlin Data Model
Kotlin for Android Developers
Pure kotlin
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
Scala collections api expressivity and brevity upgrade from java
Miracle of std lib
A quick and fast intro to Kotlin
Kotlin is charming; The reasons Java engineers should start Kotlin.
K is for Kotlin
Having Fun with Kotlin Android - DILo Surabaya
Introduction to Kotlin
Kotlin Collections
Effective Java and Kotlin
Scala for Java Developers (Silicon Valley Code Camp 13)
Ad

More from Fabio Collini (20)

PDF
Architectures in the compose world
PDF
Using hilt in a modularized project
PDF
Managing parallelism using coroutines
PDF
Kotlin Delegates in practice - Kotlin community conf
PDF
Kotlin delegates in practice - Kotlin Everywhere Stockholm
PDF
Using Dagger in a Clean Architecture project
PDF
Solid principles in practice the clean architecture - Droidcon Italy
PDF
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
PDF
SOLID principles in practice: the Clean Architecture
PDF
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
PDF
Recap Google I/O 2018
PDF
Testing Android apps based on Dagger and RxJava Droidcon UK
PDF
Intro to Retrofit 2 and RxJava2
PDF
Testing Android apps based on Dagger and RxJava
PDF
Android Data Binding in action using MVVM pattern - droidconUK
PDF
Data Binding in Action using MVVM pattern
PDF
Android Wear CodeLab - GDG Firenze
PDF
Testable Android Apps using data binding and MVVM
PDF
Introduction to Retrofit and RxJava
PDF
Testable Android Apps DroidCon Italy 2015
Architectures in the compose world
Using hilt in a modularized project
Managing parallelism using coroutines
Kotlin Delegates in practice - Kotlin community conf
Kotlin delegates in practice - Kotlin Everywhere Stockholm
Using Dagger in a Clean Architecture project
Solid principles in practice the clean architecture - Droidcon Italy
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Recap Google I/O 2018
Testing Android apps based on Dagger and RxJava Droidcon UK
Intro to Retrofit 2 and RxJava2
Testing Android apps based on Dagger and RxJava
Android Data Binding in action using MVVM pattern - droidconUK
Data Binding in Action using MVVM pattern
Android Wear CodeLab - GDG Firenze
Testable Android Apps using data binding and MVVM
Introduction to Retrofit and RxJava
Testable Android Apps DroidCon Italy 2015

Recently uploaded (20)

PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PPTX
bas. eng. economics group 4 presentation 1.pptx
PDF
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
PDF
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT
PPTX
Internet of Things (IOT) - A guide to understanding
PDF
Operating System & Kernel Study Guide-1 - converted.pdf
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
Welding lecture in detail for understanding
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
PPTX
UNIT 4 Total Quality Management .pptx
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PPTX
Sustainable Sites - Green Building Construction
PPTX
Strings in CPP - Strings in C++ are sequences of characters used to store and...
PDF
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PDF
PPT on Performance Review to get promotions
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
bas. eng. economics group 4 presentation 1.pptx
Evaluating the Democratization of the Turkish Armed Forces from a Normative P...
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT
Internet of Things (IOT) - A guide to understanding
Operating System & Kernel Study Guide-1 - converted.pdf
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
Welding lecture in detail for understanding
UNIT-1 - COAL BASED THERMAL POWER PLANTS
UNIT 4 Total Quality Management .pptx
Foundation to blockchain - A guide to Blockchain Tech
Sustainable Sites - Green Building Construction
Strings in CPP - Strings in C++ are sequences of characters used to store and...
PRIZ Academy - 9 Windows Thinking Where to Invest Today to Win Tomorrow.pdf
PPT on Performance Review to get promotions
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx

From java to kotlin beyond alt+shift+cmd+k

  • 1. From Java to Kotlin beyond Alt+Shift+Cmd+K Fabio Collini
  • 3. Kotlin can be configured in one click
  • 4. A Java class can be converted easily
  • 9. /** * Returns the first element matching the given [predicate]. * @throws [NoSuchElementException] if no such element is found. */ inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T { for (element in this) { if (predicate(element)) { return element }1 }2 throw NoSuchElementException( "Collection contains no element matching the predicate.") }3
  • 10. val list = listOf("Java", "Kotlin") val s = list.first({_v: String -> v.length > 4 _})
  • 11. val list = listOf("Java", "Kotlin") val s = list.first({_v -> v.length > 4 _})
  • 12. val list = listOf("Java", "Kotlin") val s = list.first({_ it.length > 4 _})
  • 13. val list = listOf("Java", "Kotlin") val s = list.first {_ it.length > 4 _}
  • 14. val list = listOf("Java", "Kotlin") val s = list.first { it.length > 4_}
  • 15. public static <T> T first(Iterable<T> list, Predicate<T> predicate) {_ for (T t : list) {__ if (predicate.test(t)) {___ return t; }____ }_____ throw new NoSuchElementException( "Collection contains no element matching the predicate."); }______ inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T {_ for (element in this) {__ if (predicate(element)) {___ return element }____ }____ throw NoSuchElementException( "Collection contains no element matching the predicate.") }_____
  • 16. List<String> list = Arrays.asList("Java", “Kotlin"); String s = first(list, p -> p.length() > 4);
  • 17. List<String> list = Arrays.asList("Java", “Kotlin"); String s = first(list, p -> p.length() > 4); val list = listOf("Java", "Kotlin") val s = list.first { it.length > 4 }
  • 19. inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T { for (element in this) { if (predicate(element)) { return element } } throw NoSuchElementException( "Collection contains no element matching the predicate.") } public static <T> T first(List<T> list, Predicate<T> predicate) { for (T t : list) { if (predicate.test(t)) { return t; } } throw new NoSuchElementException( “Collection contains no element matching the predicate."); }
  • 21. val list = listOf("Java", "Kotlin") val s = list.first { it.length > 4 } inline fun <T> Iterable<T>.first(predicate: (T) -> Boolean): T { for (element in this) { if (predicate(element)) { return element } } throw NoSuchElementException( "Collection contains no element matching the predicate.") }
  • 22. val list = listOf("Java", "Kotlin") var ret: String? = null for (element in list) { if (element.length > 4) { ret = element; break } } if (ret == null) throw NoSuchElementException( "Collection contains no element matching the predicate.") val s = ret
  • 24. class Person(var name:_String)_ public class Person { private String name; public Person(String name) { this.name = name; }1 public String getName() { return name; }2 public void setName(String name) { this.name = name; }3 }4
  • 25. public class Person { private long id; private String name; private int age; public Person(long id, String name, int age) { this.id = id; this.name = name; this.age = age; } public long getId()_{_return id;_} public String getName()_{_return name;_} public int getAge()_{_return age;_} }4 class Person( val id: Long, val name: String, val age: Int )_
  • 26. @Parcelize data class Person( val id: Long, val name: String, val age: Int )_: Parcelable public class Person implements Parcelable { private long id; private String name; private int age; public Person(long id, String name, int age) { this.id = id; this.name = name; this.age = age; }1 protected Person(Parcel in) { id = in.readLong(); name = in.readString(); age = in.readInt(); }2 public long getId()_{_return id;_} public String getName()_{_return name;_} public int getAge()_{_return age;_} @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person that = (Person) o; if (id != that.id) return false; if (age != that.age) return false; return name != null ? name.equals(that.name) : that.name == null; }3 @Override public int hashCode() { int result = (int) (id ^ (id >>> 32)); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + age; return result; }4 @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + ''' + ", age=" + age + '}'; }5 @Override public void writeToParcel(Parcel dest, int flags) { dest.writeLong(id); dest.writeString(name); dest.writeInt(age); }6 @Override public int describeContents() { return 0; }7 public static final Creator<Person> CREATOR = new Creator<Person>() { @Override public Person createFromParcel(Parcel in) { return new Person(in); }8 @Override public Person[] newArray(int size) { return new Person[size]; }9 }; }_
  • 27. @AutoValue public abstract class Person implements Parcelable {_ public static Person create( long id, String name, int age) { return new AutoValue_Person( id, name, age); }__ public abstract long id(); public abstract String name(); public abstract int age(); public abstract Person withName(String name); }_ @Parcelize data class Person( val id: Long, val name: String, val age: Int )_: Parcelable
  • 28. val p = Person(1, "name", 10) val p1 = p.copy(name = "newName", age = 20)_ Person p = Person.create(1, "name", 10); Person p1 = p.withName("newName");
  • 29. val p = Person(1, "name", 10) val (_, name, age) = p println("$name $age")
  • 30. data class Pair<out A, out B>( val first: A, val second: B ) : Serializable { override fun toString(): String = "($first, $second)" }_
  • 31. data class Pair<out A, out B>( val first: A, val second: B ) : Serializable { override fun toString(): String = "($first, $second)" }_ val myPair: Pair<Int, Int> = Pair(10, 20) val otherPair: Pair<Int, Int> = 10 to 20 infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
  • 32. fun myMethod(): Pair<Int, Int> { //... return 10 to 20 } val (a, b) = myMethod()
  • 34. System.out.println(b.toString()); List<Person> people = Arrays.asList(...); StringBuilder b = new StringBuilder(); for (String s : cities) { if (b.length() > 0) { b.append(", "); }3 b.append(s); }4 for (Person person : people) { City city = person.getAddress().getCity(); if (city.getRegion().equals("Tuscany")) { cities.add(city.getName() + " (" + city.getCode() + ")"); }1 }2 Set<String> cities = new TreeSet<>();
  • 35. val people = listOf(...) val s = people .map { it.address.city } .filter { it.region == "Tuscany" } .distinct() .sortedBy { it.name } .joinToString { "${it.name} (${it.code})" } println(s)
  • 37. String s = Stream.of(people) .map(it -> it.getAddress().getCity()) .filter(it -> it.getRegion().equals("Tuscany")) .distinct() .sortBy(City::getName) .map(it -> it.getName() + " (" + it.getCode() + ")") .collect(Collectors.joining(", ")); System.out.println(s);
  • 38. val people = listOf(...) val s = people .asSequence() .map { it.address.city } .map { "${it.name} (${it.code})" } .first { it.region == "Tuscany" } println(s)
  • 39. val youngest = people.minBy { it.age } val peopleByCity: Map<City, List<Person>> = people.groupBy { it.address.city } val all: Boolean = people.all { it.address.city.name == "Florence" }1 val any: Boolean = people.any { it.address.city.name == "Florence" }2 val (adults: List<Person>, minors: List<Person>) = people.partition { it.age >= 18 }
  • 40. val readOnlyList: List<Int> = listOf(10, 20, 30) val secondElement = readOnlyList[1] val mutableList: MutableList<Int> = mutableListOf(10, 20, 30) mutableList[1] = 21 val map = mapOf(1 to "ABC", 2 to "DEF") val abc = map[1] val mutableMap = mutableMapOf(1 to "ABC", 2 to "DEF") mutableMap[3] = "XYZ" val otherList = (mutableList - readOnlyList) + mutableMap.keys
  • 42. override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val myTextView = findViewById<TextView>(R.id.text) myTextView.text = "Loading..." Thread.sleep(2000) myTextView.text = "Loading something else..." Thread.sleep(2000) myTextView.text = "Done" }_
  • 43. /** * Delays coroutine for a given time without blocking * a thread and resumes it after a specified time. * ... */ suspend fun delay(time: Long, unit: TimeUnit = MILLISECONDS) { //... }
  • 45. override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val myTextView = findViewById<TextView>(R.id.text) async(UI) { myTextView.text = "Loading..." delay(2000) myTextView.text = "Loading something else..." delay(2000) myTextView.text = "Done" }async }end
  • 46. interface StackOverflowService { @GET("/users") fun getTopUsers(): Deferred<List<User>> }A async(UI) { try { val topUsers = service.getTopUsers().await() val usersUi = topUsers.map { createUserUi(it) } showInUi(usersUi) } catch (e: Exception) { showError(e) }__ }___
  • 47. interface MyService { fun login(): Deferred<String> fun loadData(token: String): Deferred<Data> }A async(UI) { try { val token = service.login().await() val data = service.loadData(token).await() showInUi(data) } catch (e: Exception) { showError(e) }__ }___
  • 48. service.login() .flatMap { service.loadData(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { data -> showInUi(data) }, { showError(it) } )end RxJavaCoroutines async(UI) { try { val token = service.login().await() val data = service.loadData(token).await() showInUi(data) } catch (e: Exception) { showError(e) }__ }___
  • 51. RxJava Coroutines-> RxJavaCoroutines -> rxCompletable, rxMaybe, rxSingle, rxObservable, rxFlowable CompletableSource.await, MaybeSource.await, MaybeSource.awaitOrDefault, MaybeSource.openSubscription, SingleSource.await, ObservableSource.awaitFirst, ObservableSource.awaitFirstOrDefault, ObservableSource.awaitFirstOrElse, ObservableSource.awaitFirstOrNull, ObservableSource.awaitLast, ObservableSource.awaitSingle, ObservableSource.openSubscription, ObservableSource.iterator github.com/Kotlin/kotlinx.coroutines/tree/master/reactive/kotlinx-coroutines-rx2
  • 52. My 2 cents Suspending methods are easier to use than RxJava Singles Observables/Flowables are the best abstraction for a stream of data
  • 53. async(UI) { try { val token = service.login().await() val data = service.loadData(token).await() showInUi(data) } catch (e: Exception) { showError(e) }__ }___
  • 54. async(UI) { try { val token = service.login().await() val data = service.loadData(token).await() val otherData = service.loadOtherData(token).await() showInUi(data, otherData) } catch (e: Exception) { showError(e) }__ }___
  • 55. async(UI) { try { val token = service.login().await() val data = service.loadData(token) val otherData = service.loadOtherData(token) showInUi(data.await(), otherData.await()) } catch (e: Exception) { showError(e) }__ }___
  • 56. async(UI) { try { val token = service.login().await() updateProgress() val data = service.loadData(token) val otherData = service.loadOtherData(token) showInUi(data.await(), otherData.await()) } catch (e: Exception) { showError(e) }__ }___
  • 57. async(UI) { try { withTimeout(10, SECONDS) { val token = retry(3) { service.login().await() }T updateProgress() val data = service.loadData(token) val otherData = service.loadOtherData(token) showInUi(data.await(), otherData.await()) }B } catch (e: Exception) { showError(e) }__ }___
  • 58. async(UI) { try { withTimeout(10, SECONDS) { val token = retry(3) { service.login().await() }T updateProgress() val data = service.loadData(token) val otherData = service.loadOtherData(token) showInUi(data.await(), otherData.await()) }B } catch (e: Exception) { showError(e) }__ }___ suspend fun <T> retry(times: Int, block: suspend () -> T): T { repeat(times - 1) { try { return block() } catch (ignored: Exception) { } } return block() }
  • 60. class TokenHolder {0 var token = "" }1
  • 61. class TokenHolder(val prefs: SharedPreferences) {0 var token = "" }1
  • 62. class TokenHolder(val prefs: SharedPreferences) { var token get() = prefs.getString("token", "") set(value) = prefs.edit().putString("token", value).apply() }1
  • 63. class TokenHolder(prefs: SharedPreferences) { var token by prefs.string() }1
  • 64. class TokenHolder(prefs: SharedPreferences) { var token by prefs.string() }1 fun SharedPreferences.string( defaultValue: String = "", key: String? = null ): ReadWriteProperty<Any, String> { return object : ReadWriteProperty<Any, String> { override fun getValue(thisRef: Any, property: KProperty<*>): String { return getString(key ?: property.name, defaultValue) }2 override fun setValue(thisRef: Any, property: KProperty<*>, value: String) { edit().putString(key ?: property.name, value).apply() }3 }4 }5
  • 65. class TokenHolder(prefs: SharedPreferences) { var token by prefs.string() }1 tokenHolder.token += "ABC" prefs.edit().putString( "token", prefs.getString("token", "") + "ABC" ).apply()
  • 66. Wrapping up inline methods to avoid extra classes functional code is natural in Kotlin code can be simplified using data classes, coroutines and delegates
  • 67. Links AutoValue https://github.com/google/auto/blob/master/value/userguide/index.md Lightweight Stream https://github.com/aNNiMON/Lightweight-Stream-API Guide to kotlinx.coroutines by example https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md Kotlin coroutines, a deeper look https://medium.com/@elizarov/kotlin-coroutines-a-deeper-look-180536305c3f Kotlin delegates in Android development - part 1 https://hackernoon.com/kotlin-delegates-in-android-development-part-1-50346cf4aed7 Kotlin delegates in Android development - part 2 https://proandroiddev.com/kotlin-delegates-in-android-development-part-2-2c15c11ff438