詳解Kotlin:forEach也能break和continue
詳解Kotlin:forEach也能break和continue
這樣的問題。也就是說,他們想用forEach而不是for循環(huán),因為這很fp,很洋氣(我也喜歡),
但是他們又想使用break和continue,也就是普通的流程控制語句中的控制語句。
這很不fp,因為原本有filter是用于完成這個工作的,還有flapMap。BennyHuo在他發(fā)的文章里面也說的是這種方法。
filter很fp,但是會導(dǎo)致兩次遍歷,這樣的話給人一股效率很低的趕腳。而Java8的Stream API就只會遍歷一次,
而且很fp。但是它會有l(wèi)ambda對象的產(chǎn)生而且實現(xiàn)超復(fù)雜(我沒看過,不清楚),而Kotlin的集合框架可是能inline掉lambda的,
少產(chǎn)生了多少對象啊,怎么能和辣雞Java同流合污呢?
有人提到使用label return,比如:
fun main(ags: Array<String>) {
(0..100).forEach {
if (50 <= it) return@forEach
println(it)
}
}
但是他做了實驗之后發(fā)現(xiàn)這玩意只能相當(dāng)于continue,也就是說你只能跳出當(dāng)前循環(huán),然后還是會繼續(xù)下一輪。
講道理這個你仔細想想就可以發(fā)現(xiàn)。為了搞清楚其中的道理,我們自己實現(xiàn)一個forEach。
fun Pair<Int, Int>.forEach(block: (Int) -> Unit) {
for (i in first..second) block.invoke(i)
}
然后調(diào)用一下:
Pair(1, 100).forEach(::println)
沒毛病老鐵。
然后你會發(fā)現(xiàn),你在函數(shù)體內(nèi)對block產(chǎn)生了(second - first)次調(diào)用,不論你怎么return,都只會跳出這個block,
它并不影響你之后繼續(xù)調(diào)用這個block,也就是說這個for循環(huán)不受block行為的影響。
看起來無解了,那怎么辦呢?
那么就讓我來拯救你們吧。
fun main(ags: Array<String>) {
run outside@ {
(0..20).forEach inside@ {
if (10 <= it) return@outside
println(it)
}
}
}
編譯之后運行結(jié)果:
0 1 2 3 4 5 6 7 8 9 Process finished with exit code 0
吶,跳出去了。
就是這樣:
run breaking@ {
(0..20).forEach continuing@ {
if (10 <= it) return@breaking
println(it)
}
}
上面這是break,運行結(jié)果就上面那樣。
下面這是continue,運行結(jié)果就是continue的效果。為了讓效果表現(xiàn)的明顯,我把println復(fù)制了一下,
分別在if前后,這樣可以很清楚地看到效果。
run breaking@ {
(0..20).forEach continuing@ {
print(it)
if (10 <= it) return@continuing
println(it)
}
}
運行一下:
00 11 22 33 44 55 66 77 88 99 1011121314151617181920 Process finished with exit code 0
而且只進行了一次迭代,效率看起來也比較高。
如何證明只有一次迭代?我使用jd-gui逆向了剛才的代碼,結(jié)果:
public final class _5Kt
{
public static final void main(@NotNull String[] args)
{
Intrinsics.checkParameterIsNotNull(args, "args");
int $i$a$1$run;
Iterable $receiver$iv = (Iterable)new IntRange(0, 20);
int $i$f$forEach;
for (Iterator localIterator = $receiver$iv.iterator(); localIterator.hasNext();)
{
int element$iv = ((IntIterator)localIterator).nextInt();int it = element$iv;
int $i$a$1$forEach;
System.out.print(it);
if (10 <= it) {
break;
}
System.out.println(it);
}
}
}
確實只有一次,而且jd-gui直接把我的行為反編譯為break了。服不服?
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
SpringBoot中使用com.alibaba.druid.filter.config.ConfigTools對數(shù)據(jù)庫
這篇文章主要介紹了SpringBoot中使用com.alibaba.druid.filter.config.ConfigTools對數(shù)據(jù)庫密碼加密的方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-01-01
已有的springcloud+mybatis項目升級為mybatis-plus的方法
這篇文章主要介紹了已有的springcloud+mybatis項目升級為mybatis-plus,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
解析spring-security權(quán)限控制和校驗的問題
這篇文章主要介紹了解析spring-security權(quán)限控制和校驗的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03
java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼)
為避免繁瑣的注冊登陸,很多平臺和網(wǎng)站都會實現(xiàn)三方登陸的功能,增強用戶的粘性。這篇文章主要介紹了java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼),避免做微信登錄開發(fā)的朋友們少走彎路2022-12-12
Maven?繼承父工程時的relativePath標(biāo)簽詳細解析
這篇文章主要介紹了Maven?繼承父工程時的relativePath標(biāo)簽解析,通過本文學(xué)習(xí)你需要注意子模塊想要用父模塊pom中的版本,請注意配置relativePath屬性,需要的朋友可以參考下2022-12-12
springboot-mybatis/JPA流式查詢的多種實現(xiàn)方式
這篇文章主要介紹了springboot-mybatis/JPA流式查詢,本文給大家分享三種方式,每種方式結(jié)合示例代碼給大家講解的非常詳細,需要的朋友可以參考下2022-12-12
SpringBoot項目離線環(huán)境手動構(gòu)建的過程
文章介紹了如何在IntelliJ IDEA中手動創(chuàng)建一個Spring Boot項目,并詳細講解了pom.xml文件的配置和基本項目結(jié)構(gòu)的設(shè)置,感興趣的朋友跟隨小編一起看看吧2025-01-01

