新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「小姐姐味道」,作者小姐姐養(yǎng)的狗。轉(zhuǎn)載本文請(qǐng)聯(lián)系小姐姐味道公眾號(hào)。

創(chuàng)新互聯(lián)長(zhǎng)期為近1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開(kāi)放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為萬(wàn)山企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、成都做網(wǎng)站,萬(wàn)山網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開(kāi)發(fā)。
Java的Optional非常好用。我們一般使用Optional做非空處理,省去if的處理。主要的目的,就是為了解決Java中臭名昭著的空指針異常。
比如我們?cè)谄匠5木幋a中,經(jīng)常遇到對(duì)輸入?yún)?shù)的非空判斷。
- public void getXXX(Map
params) { - Map
map = params; - if (map == params) {
- map = new HashMap<>();
- }
- }
這種代碼一多,我們的程序就會(huì)慢慢變成shit mountain。這個(gè)時(shí)候就可以使用Optional進(jìn)行改造。
- public void getXXX(Map
params) { - Map
map = Optional.ofNullable(params).orElse(new HashMap<>()); - }
代碼行數(shù)少了,邏輯清晰,同時(shí)自己的績(jī)效也降低了 :)。
1. 復(fù)雜例子
看一個(gè)比較復(fù)雜的例子。
假如我們需要的數(shù)據(jù)層次比較深。
- String cityCode = customer.getAddress().getCity().getCityCode().substring(0,3);
這樣獲取是不合理的,因?yàn)槠渲械哪骋画h(huán),可能是空,會(huì)拋出空指針的。所以,我們需要一層層的進(jìn)行判斷。
- public void getCityCode(Customer customer) {
- String cityCode = "000";
- if (customer != null) {
- Address address = customer.getAddress();
- if (null != address) {
- City city = address.getCity();
- if (city != null) {
- String code = city.getCityCode();
- if (null != code && code.length() >= 3) {
- cityCode = code.substring(0, 3);
- }
- }
- }
- }
- System.out.println(cityCode);
- }
使用Optional的lambda語(yǔ)法,我們可以把代碼改成下面這樣:
- public void getCityCode(Customer customer) {
- String cityCode = Optional.ofNullable(customer)
- .map(c -> c.getAddress())
- .map(a -> a.getCity())
- .map(c -> c.getCityCode())
- .filter(s -> s.length() >= 3)
- .map(s -> s.substring(0, 3))
- .orElse("000");
- }
代碼是不是顏值很高?
顏值雖高,下面還是要點(diǎn)一些偏門的重點(diǎn)內(nèi)容。
2. Optional的隱秘內(nèi)容
其實(shí),早在Java8發(fā)布之前(2014),guava就有了類似的工具,但由于當(dāng)時(shí)并沒(méi)有l(wèi)ambda語(yǔ)法,所以只能做些簡(jiǎn)單的應(yīng)用。
Guava的optional支持序列化,可以在RPC框架方法中返回,但是一般很少用。
Java的Optional卻根本無(wú)法序列化。為什么java8的Optional沒(méi)有實(shí)現(xiàn)序列化,這里有個(gè)討論,可以看看http://mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/003186.html
另外Java8比Guava多了ifPresent、map、 filter、 flatMap、 orElseThrow這些方法。鑒于現(xiàn)在使用Guava Optional的人越來(lái)越少,不提也罷。
Optional會(huì)對(duì)GC有一定壓力,如果開(kāi)發(fā)底層框架,還是慎重使用,netty就曾經(jīng)過(guò)測(cè)試,最后放棄了Optional。
但我還是喜歡用。誰(shuí)讓國(guó)內(nèi)大多數(shù)都是cruder呢?
3. Try為何物?
長(zhǎng)期使用使用Java編碼的Javaer,在見(jiàn)了Scala、Kotlin一類的語(yǔ)言后,會(huì)有一種驚艷的感覺(jué)。但這些包實(shí)在是太大了,引入有一定的成本,只能眼巴巴的饞她們的身子。
但是,Java 標(biāo)準(zhǔn)庫(kù)對(duì)函數(shù)式編程的 API 支持相對(duì)比較有限。有沒(méi)有一種輕量級(jí)的方式,來(lái)增強(qiáng)我們的Java庫(kù)呢?要是能和Lambda表達(dá)式結(jié)合起來(lái),那就更妙了。Vavr就是這樣一個(gè)簡(jiǎn)單的Jar包,讓我們的代碼,寫起來(lái)更加流暢。
它的maven坐標(biāo)是:
io.vavr vavr 0.10.3
下面是一段偉大的睡眠排序法的代碼:
- public class SleepSort implements Runnable {
- private int num;
- public SleepSort(int num) {
- this.num = num;
- }
- @Override
- public void run() {
- try {
- Thread.sleep(num * 10);
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.out.print(num + " ");
- }
- public static void main(String[] args) {
- int[] nums = {5, 22, 10, 7, 59, 3, 16, 4, 11, 8, 14, 24, 27, 25, 26, 28, 23, 99};
- Arrays.stream(nums).forEach(n->new Thread(new SleepSort(n)).start());
- }
- }
其中的Run部分,太多無(wú)用的信息,我們可以使用Try來(lái)改造。
我們可以簡(jiǎn)化為下面兩行:
- Try.run(()->Thread.sleep(num*10))
- .andThen(()->System.out.print(num + " "));
它支持非常多的方法,可以完成大多數(shù)后續(xù)的業(yè)務(wù)處理。比如,在onFailure方法里,加入對(duì)異常信息的日志記錄。
而常見(jiàn)的jackson json的處理,可以簡(jiǎn)化成下面的代碼:
- String json = Try.of(() -> objectMapper.writeValueAsString(str)).getOrElse("{}");
Try就是這么好用。最重要的是,vavr的大小只有800多kb。
4. vavr的更多操作
vavr支持Tuple(元組)、Option、Try、Either、集合便捷操作、多元函數(shù)、柯里化方法(curring)等。
可以看一下vavr版本的if else。下面是四個(gè)分支的代碼。里面這些奇怪的符號(hào),證明它也只是語(yǔ)法糖。
- public String vavrMatch(String input) {
- return Match(input).of(
- Case($("a"), "a1"),
- Case($("b"), "b2"),
- Case($("c"), "c3"),
- Case($(), "unknown")
- );
- }
再比如,你想要定義一個(gè)函數(shù),而不是一個(gè)類,在Java中可以使用Function。但可惜的是,Java的Function只支持一個(gè)參數(shù)。
使用Vavr的Function,最多支持22個(gè)參數(shù)!
再比如,你想要在一個(gè)方法中,返回多個(gè)值。這個(gè),在python中很容易實(shí)現(xiàn),在Java中就不得不定義一個(gè)Class去接收。
元組,就可以支持多個(gè)返回值的組合。比如下面的代碼:
- // (Java, 8)
- Tuple2
java8 = Tuple.of("Java", 8); - // "Java"
- String s = java8._1;
- // 8
- Integer i = java8._2;
vavr支持一次性返回8個(gè)值。
另外,還有l(wèi)azy等小工具。比如延遲獲取值。
- Lazy
lazy = Lazy.of(Math::random); - lazy.isEvaluated(); // = false
- lazy.get(); // = 0.123 (random generated)
- lazy.isEvaluated(); // = true
- lazy.get(); // = 0.123 (memoized)
這樣的擴(kuò)展方法有很多。但我最常用的,還是Try和元組。它讓代碼變的更加優(yōu)雅,表達(dá)意圖也更加清晰。
哦對(duì)了。resilience4j就重度使用了vavr,就是那個(gè)Hystrix不再更新之后,官方推薦的那個(gè)熔斷組件。
作者簡(jiǎn)介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。我的個(gè)人微信xjjdog0,歡迎添加好友,進(jìn)一步交流。
分享名稱:用過(guò)Optional;那用過(guò)Try么?
當(dāng)前路徑:http://m.5511xx.com/article/dhgcpjj.html


咨詢
建站咨詢
