比学习新技术更重要的是思维的改变
程序員是一個苦逼的行業,其中重要的一點就是行業專業知識更新的速度非常快,超過其他絕大部分行業,尤其是前臺開發,這些天各種框架思想如雨后春筍層出不窮,有時候買了一本書,書還沒有學完,技術可能已經更新或者被淘汰。那么,作為程序員的我們,怎么樣才能不被爆炸的知識擊昏,切實掌握真正屬于自己的技術呢?
從我個人的心得來說,學習技術應該重點學習那種新思想新角度的技術,并使用新的思維來寫新學習的技術。大部分技術人員的問題不在于前者,而在于學習了新技術,卻還是使用老的思維來寫新技術,就好比用馬拉火車一樣,寫者落淚看者傷心!
舉例,在前臺開發中,MVVM框架的出現,相對于jquery天下的前臺是一個非常大的改變,我們學習mvvm框架的時候,首先第一步要從思維上認識到這2種技術的不同,要理解數據驅動概念,理解 “jquery是死的,mvvm是活的” 這點,而不是只是把mvvm框架當作一個模板框架來使用。而在實際工作中,出現過有些水平較差的開發人員,還在使用jquery的思維來寫vue的框架,結果是vue的好處沒有享受到,整個開發部署過程還變得復雜。
后臺開發里面,jdk8由于接口默認實現特性,絕對算得上是一個里程碑,其中最重要的函數式編程的思想。lambda表達式和stream流的學習不算復雜,但你學會了api的使用,你就真的掌握了函數式編程嗎?我看未必!
我們來看一道題目,計算 集合中 DeptId 和 Type 相同的數據的num總和。需求很常見,看著很簡單,各位寫寫看?
import?lombok.Data;import?java.util.ArrayList; import?java.util.List; import?java.util.stream.Collectors;/***??計算?集合中?DeptId?和?Type?相同的數據的num總和*/ public?class?Test?{public?static?void?main(String[]?args)?{List<DataBean>?totalStocks?=?new?ArrayList<>();DataBean?stock1?=?new?DataBean();stock1.setDeptId(2);stock1.setType(2);stock1.setNum(2);totalStocks.add(stock1);DataBean?stock2?=?new?DataBean();stock2.setDeptId(2);stock2.setType(2);stock2.setNum(3);totalStocks.add(stock2);DataBean?stock3?=?new?DataBean();stock3.setDeptId(3);stock3.setType(3);stock3.setNum(5);totalStocks.add(stock3);DataBean?stock4?=?new?DataBean();stock4.setDeptId(3);stock4.setType(3);stock4.setNum(4);totalStocks.add(stock4);DataBean?stock5?=?new?DataBean();stock5.setDeptId(4);stock5.setType(4);stock5.setNum(10);totalStocks.add(stock5);}}@Data class?DataBean?{private?int?type;private?int?deptId;private?int?num; }這條題目是我群里的人問的,他自己用stream寫了一個,覺得寫的不好,問我應該怎么樣寫,我當時把這道題目發在群里面,結果發現大部分寫得都不太好(建議大家先不要往下看,自己打開ide寫寫試試)。其中一個常見錯誤是stream操作中修改了數據,如
//group Map<String,?List<DataBean>>?gourps?=?totalStocks.stream().collect(Collectors.groupingBy(e?->?e.getDeptId()?+?":"?+?e.getType()));//?reduce(錯誤的寫法) List<DataBean>?result?=?gourps.values().stream().reduce(list?->?list.stream().reduce((e1,?e2)?->?{e2.setNum(e1.getNum()?+?e2.getNum());return?e2; }).get()) //?toList .collect(Collectors.toList());System.out.println(result);還有一種是,自己new了一個ArrayList,然后再流操作之中往list里面加數據的。至于group2次的就不評論了。
我們學習函數式編程里面,函數式強調函數必須是純函數,不能修改數據,而且是冪等,在stream里面,任何修改數據的行為都是不應該的,修改數據的時候應該返回新對象。所以在里面set數據的,或者往list里面增加數據的,都是不好的寫法!我們學習了函數式編程,就應該遵守他的規則和思想。上面的題目,我的寫法如下:
List<DataBean>?result?=?totalStocks.stream()//group.collect(Collectors.groupingBy(e?->?e.getDeptId()?+?":"?+?e.getType()))//?分組后的list做reduce.values().stream().map(list?->?list.stream().reduce(Test::combine).get())//?收集到list.collect(Collectors.toList());System.out.println(result);private?static?DataBean?combine(DataBean?e1,?DataBean?e2){DataBean?e?=?new?DataBean();e.setDeptId(e1.getDeptId());e.setType(e1.getType());e.setNum(e1.getNum()?+?e2.getNum());return?e; }我們在看另外一種場景,由于不按照函數式思維編寫代碼,在不同的jdk版本中,結果不一樣,可能導致bug
import?java.lang.management.ManagementFactory; import?java.util.ArrayList; import?java.util.Collections; import?java.util.List;class?Demo{public??String?msg?=?"初始值"; }public?class?LambdaDemo2?{public?static?void?main(String[]?args)?{System.out.println("jdk版本:"+ManagementFactory.getRuntimeMXBean().getVmVersion());List<Demo>?demos??=?new?ArrayList<Demo>();demos.add(new?Demo());demos.add(new?Demo());//?這里peek中修改了對象,產生了副作用(side-effects)long?count?=?demos.stream().peek(demo?->?demo.msg?=?"peek中修改了").count();System.out.println(count);//?jdk8下下面的demo已經改變//?jdk10下沒有demos.stream().forEach(demo?->?System.out.println(demo.msg));} }peek函數,按照函數式編程的規范,是調試用的,是個中間操作,如果你在里面修改了對象,看上去沒有問題,但是在JDK8和JDK10中,2種運行結果不一致,JDK10種peek方法直接跳過了。
所以,我們學習一個新技術,可以從下面幾個層次了解推進,產生的背景?和之前的技術有什么區別?他的思想(風格)是什么?主要的API和套路。如函數式編程,要了解和命令式編程的區別,一開始可能不太理解,多看幾個貼,先有個模糊的概念。然后再看看函數式是怎么樣的風格?而不是當作一個新的類庫/工作類來使用(很多人是當作工具類使用的想法)。最后系統學習api。當然最重要的還是多寫,寫完之后看看是不是符合函數式編程的風格,如果看著別扭那就是那個環節出現了問題。
總結,我們學習新技術的同時,除了API的使用之外,最重要的是改變思維,使用新技術的思維來寫新的代碼,一開始可能有點痛苦,但多寫幾次之后就會適應,就會感覺到新的技術給我們帶來的好處,這是成長的必經之路!
總結
以上是生活随笔為你收集整理的比学习新技术更重要的是思维的改变的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2019年我建议你做好三件事情
- 下一篇: 漫画:通俗易懂的进程与线程解释