當Android遇上Kotlin — Day4

Locus Yu
Locus Yu
Sep 1, 2017 · 2 min read
Image for post
Image for post

Lambda

  • 將函數當作值的功能傳入
// 語法結構
input(parameters):
不輸入:()
單個輸入:x
多個輸入:(int x, int y)或簡寫(x,y)
body:
什麼都不做:{}
單行不回傳值:print("NO")
多行不回傳值:
{
print("NO");
print("NO2");
}
單行回傳值:x+y
多行回傳值:
{
x++;
y-=x;
return x+y;
}
  • 使用Runnable來解釋Lambda
// Android
Runnable runnbale = Runnable() {
public run() {
System.out.println("run me!");
}
};
// Lambda
Runnable runnbale = () -> System.out.println("run me!");
  • 使用Lambda時,不會多new一個實體出來,而是將Lambda的body區塊先放到記憶體中,透過Call Function的方式來進行呼叫,如此一來可以提升程式效能
// Java
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
/* actions on click */
}
});
// Lambda
button.setOnClickListener { view -> /* actions on click */ }

以前必須自己實作所有東西的習慣,現在可以透過Lambda和相關的操作子來改正這習慣

//找出最大年齡fun findTheOldest(people: List<Person>) {
var maxAge = 0
var theOldest: Person? = null
for (person in people) {
if (person.age > maxAge) {
maxAge = person.age
theOldest = person
}
}
print(theOldest)
}
val people = listOf(Person("Alice", 29), Person("Bob", 31))
findTheOldest(people)
輸出:[Person(name=Bob, age=31)]// 透過Kotlinval people = listOf(Person("Alice", 29), Person("Bob", 31))
print(people.maxBy { it.age })
輸出:[Person(name=Bob, age=31)]
  • 如何簡化Lambda
people.maxBy { it.age }// 其實最原始的模樣是
people.maxBy({ p: Person -> p.age }) //將person傳入,並回傳age
// 如果他是函數中唯一的參數時,可以將他放置在圓括號外面
people.maxBy() { p: Person -> p.age }
// 並可以將圓括號刪除
people.maxBy { p: Person -> p.age }
// 去除參數類型
people.maxBy { p -> p.age }
// 最後使用it來代替這參數
people.maxBy { it.age }

  • 篩選元素操作子(filter)
val people = listOf(Person("Alice", 29), Person("Bob", 31))
people.filter { it.age > 30 }
輸出:[Person("Bob", 31)]
  • 修改元素操作子(map)
val people = listOf(Person("Alice", 29), Person("Bob", 31))
people.map { it.name }
輸出:[Alice, Bob]
  • 查找元素操作子(find or firstOrNull)
val people = listOf(Person("Alice", 27), Person("Bob", 31))
people.find { it.age <= 27 }
people.firstOrNull { it.age <= 27 }
輸出:[Person(name=Alice, age=27)]
  • 組合元素操作子(groupBy)
val list = listOf("a", "ab", "b")
list.groupBy { String::first} // first 為String的擴展函數,取得第一個字元
輸出:{a=[a, ab], b=[b]}
  • 扁平化集合元素操作子(flatMap)或(flatten)
val strings = listOf("abc", "def")
strings.flatMap { it.toList() }
輸出:[a, b, c, d, e, f]
如果只是單純要扁平化所有集合元素,可直接使用flatten來取代
val strings = listOf("abc", "def").flatten()
  • 將Lambda轉變為函數式接口
  • 假設有一個需要返回函數式接口的方法,你無法直接返回一個Lambda,因為對於Lambda來說他只是一個程式區塊,而不是一個物件,所以你無法直接返回一個Lambda給此函數,必須將他包裝成SAM構造函數
// Java
Runnable runnable = new Runnable() {
@override
public void run() {
...
}
};
// Kotlin
fun createRunnable(): Runnable {
return Runnable { ... }
}
  • 實作一個可以重用的Lambda函數式接口
val listener = OnClickListener { view ->
val text = when(view.id) {
R.id.button1 -> "First button Clicked"
R.id.button2 -> "Second button Clicked"
else -> "Unknown"
}
toast(text)
}
button1.setOnClickListener(listener)
button2.setOnClickListener(listener)

fun alphabet(): String {
val result = StringBuilder()
for (letter in 'A'..'Z') {
result.append(letter)
}
result.append("\nNow I know the alphabet!")
return result.toString()
}
// 使用with函數重構
fun alphabet(): String {
val stringBuilder = StringBuilder()
return with(stringBuilder) {
for(letter in 'A'..'Z') {
this.append(letter)
}
append("\nNow I know the alphabet!")
this.toString()
}
}

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store