這些知識點全面快速復習Java面試題

      網友投稿 885 2022-05-30

      前言

      面試別人,對我來說是一件新奇事,以前都是別人面試我。我清楚地知道,我在的地域與公司,難以吸引到中國的一流軟件人才。所以,我特地調低了期望,很少問什么深入的技術問題,只問一些廣泛的、基礎的。我只要最終給Leader一句“這個人技術還行/很好/非常好”,就行了。至于其它能力、綜合水平,由別人把關。為此,在挑選唯一的一道筆試題時,我特別地上心。

      首先,我不敢用網上那些廣為流傳的,比如Leetcode、《程序員面試寶典》里的題——這些都太難了!正兒八經做,其實很少有人能在1小時內完美做出來,除非之前遇到過。我本人也并非什么思維敏捷的牛人,不然也不會混得這么慘。正所謂己所不欲,勿施于人,我也不希望以后別人考我特別麻煩的算法題,所以自創了一道特別簡單的。

      其次,對(Android平臺的)Java程序員來說,大多數情況下不需要寫什么復雜的算法。相反,Java層主要做的是界面控制、業務邏輯、數據流之類的,更提倡代碼的簡單和可讀,盡量用既有的公共類庫,不惜損失一些運行效率。拿一道復雜的算法題,考一個Java程序員,多少有點刁難人。

      最后,還是那個薪資待遇和人才梯度問題。沒有Google的工資,就別考Google的題;沒有Google的向心力,就別期待有Google級別的人才來面試。

      亮題

      以下有一個 static method,類外會調用它,一個個地插入一些元素進入一個List。可以改變這個List內容的,只有這一個method,要求任何時候這個List都是有序的。比如,依次插入3、2、1、2,我希望List的順序是1、2、2、3。

      class?Solution?{

      private?static?List?sSorted?=?new?LinkedList<>();

      public?static?void?addElement(int?e)?{

      //?TODO:?Insert?e?to?sSorted?and?make?sure?sSorted?is?always?sorted.

      }

      }

      我會給出15分鐘的時間,而其實往往會再多給10分鐘。(有興趣,你可以停在這試試。相信在看文章這種輕松的環境下,理清這道題的思路也就10~30秒。)

      (為什么下限是10秒呢?唉……一不小心暴露了我智商的峰值。我實際問過一些同事,他們通常在理解的同時,就立刻給出了正確的思路,過程不足5秒,其中甚至包括一個硬件工程師,和一個只負責溝通和文檔的妹子。)

      提示

      在過程中,我會逐步給出一些提示,從接口到思路,都會主動提供,其它也基本有問必答。如果單純考算法,C語言才是最合適的,因為它沒有什么高級的工具類,什么復雜點的都得自己寫。而Java,則有一些“基礎”類庫是難以記憶的。比如前面出現的java.util.List,就沒有多少人能在紙上寫出它的常用接口。

      我并不想考察什么死記硬背,在這個時代,斷網后本來就沒幾個程序員能正常編程。所以我會主動提供一份List的不完全接口列表。

      public?interface?List?extends?Collection?{

      public?void?add(int?location,?E?object);

      public?void?add(E?object);

      public?void?clear();

      public?boolean?contains(Object?object);

      public?boolean?equals(Object?object);

      public?E?get(int?location);

      public?int?indexOf(Object?object);

      public?boolean?isEmpty();

      public?E?remove(int?location);

      public?E?set(int?location,?E?object);

      public?int?size();

      }

      我沒有給出完全的接口,因為給多了無疑是誤導人。真正能用上的接口其實也就3個,但我也總不能只給3個,提示得太明顯,也限制了對方的思路。所以,給出了可能用得上的這幾個。我也沒給出注釋,因為有聲明就已經夠了。而且如果對方問起,我也會給出解釋。

      一開始我想,考一個排序算了。但是轉念一想,這也太不負責任了。對面要是背一道冒泡排序的解法上來,達不到考察技術水平的目的,Boss也不會認可。本著“放水不能太明顯”的原則,我想考插入排序,并且把題目弄得沒多少人見過。

      排序是一類基本算法,合格的程序員至少會一種。大多數人都只會入門級的冒泡排序,而我更喜歡插入排序,原因……你會明白的。

      插入排序,其實就是把數組或列表在邏輯上分成兩部分,一部分是待排序的,一部分是有序的。一開始,有序的部分只有一個元素(或者一個都沒有),然后從待排序的部分里一個個抽出來,插入到有序的部分。等元素都插入到了有序的部分,排序過程也就完成了。

      你看,也就***N次的事。而我這道題,就是只考插入排序算法的一半,會插就行。

      在面試過程中,我甚至常常親自解釋插入排序是怎么回事——放水到這個份上,我都不忍心再退步了。

      真正的考察點

      這是一份Android平臺的開發工作,Boss要求的是能干活、干好活。我給出的建議要求是:

      熟悉Java。

      有良好的溝通、表達能力。

      學習能力強,喜歡不斷拓展計算機領域的知識。

      有良好的編碼習慣,愿意為代碼的簡潔、優雅而反復修改。

      我建議Boss放棄學歷和工作年限的要求,技術崗位就應該只考察技術(和其它基本能力),不應該考察技術的間接證明。

      Java是Android的基本功(我們不玩Kotlin、Scala、React Native等新花樣),這門語言如果不扎實,那至少得帶半年。

      我沒有在Android崗明確地要求考察Android,是因為Android的那些東西相對來說容易學習。即便是毫無經驗的新手,要搞清楚什么“四大組件”“五大布局”,也就一兩天的事。而如果Java不夠扎實,各種肉眼可見的大小bug就會層出不窮,知識盲點一兩年都補不完。

      溝通是職場基本功。如果話都說不清,那么會顯著降低團隊的溝通效率。而且,我個人認為,話說不清的人,代碼一定寫不好。語言條理清晰,邏輯層次分明,體現到代碼上,就是簡潔、明朗。

      學習能力、求知欲,是作為一個程序員的基本素養。因為,大部分人的工作,類似于在一堆按鈕中,找到合適的那個按下去;而程序員的工作,往往是閉著眼睛這么干。開發工程師通常是在一堆未知(沒讀過的代碼、不知道的接口)中,把一小部分變成已知(讀懂了的代碼或接口),進行一些增刪改,最后達成外界(產品經理、設計師、測試工程師)賦予的業務目標。

      一些職業賣口水,一些職業賣口才。一些職業賣青春,一些職業賣肉體(咳咳,我說的是空姐和搬磚,想歪的去面壁)。一些職業賣知識,一些職業賣能力。

      程序員,或者說軟件開發工程師,賣的是學習能力(其實也包括青春和肉體),快速學會各種知識,找到那些藏在屏幕外的按鈕,并且正確的按下去。比如,像Bash這類Command line工具,就是自己敲命令出來執行,而不是去界面上找功能對應的按鈕;而程序設計、實現,就是去發現、或者創造一種解決問題的辦法,然后用代碼表達出來——你看,都是在干一些反UI、UX設計的事。唯有不斷地學習,才能提高效率,把自己從加班中解脫出來,把項目從bug中拯救出來。所以,厭學的人當不了好程序員,也干不長。

      編碼習慣,相對次之。部分觀點認為,這東西伴隨一生,如果一開始沒有好習慣,這輩子都沒辦法改了。Boss就是這么認為的,我倒是不這么認為。我相信編碼習慣的可塑性是很高的——你不按規范寫,我不給你merge,改不改?

      但是,編碼習慣作為程序員的軟技能,還是可以一定程度上看出其技術素養、代碼質量的。至于優雅什么的,我其實沒有真的敢這么期待。

      所以,我這道題其實是考察這四點。

      能寫出來,并且無明顯問題,代表Java基本功扎實。

      理解我對題目的描述,和我確認清楚題目的細節,這是看溝通能力。

      List接口不知道,我給你啊;插入排序不會,我教你啊;其它還有什么不會,你問啊——這是在考察學習能力。

      代碼的字里行間,可以明顯看出編碼習慣。

      面試結果

      總體來說,我很傷心。

      第一位就讓我很傷心,當我看了他前兩行代碼,就不忍心接著往下看:

      private?static?List?sSorted?=?new?LinkedList<>();

      public?static?void?addElement(int?e)?{

      if?(null?==?sorted)?{

      sorted.add(e);

      }

      //?I?couldn't?read?more!

      第一行就編譯不過。如果他對Java的一些命名規范有一定的了解,就絕不會把sSorted寫成sorted。(當然,sSorted也許并不是合適的命名方式,因為s和m這類前綴有些冗余。我通常遵守Android源碼的通用規范,它是有這類前綴的。)

      第二行必然拋出NullPointerException,而不知道是該慶幸還是悲傷的是,它永遠執行不到。根據我已經給出的一個接口addElement,和可以猜到或者問出來的讀取接口,都是不會把sSorted變成null的。這體現了溝通、理解能力的一點問題。

      此外,即使sSorted因為什么bug而變成null,這里也不應該做處理,而是任其拋出NullPointerException,或者轉義一下,主動拋出IllegalStateException。否則,此處將變成一個不會crash的隱藏bug。不能用正常處理,代替異常處理;當然,也不能用異常處理,代替流程控制。

      另外,更令我失望的是,有一位是這么寫的:

      for?(int?i?=?0;?i?

      if?(e?==?sSorted.get(i))?{

      sSorted.add(i,?e);

      }

      }

      我問他,如果這個元素不在這個List里存在怎么辦?如果這個List是空的怎么辦?他頓時一囧,我也一起囧,心想自己是不是太壞了。

      還有一位,仿佛聽見了我這幾個問題,他竟然一一作答:

      if?(sSorted.size?==?0)?{

      sSorted.add(e);

      return;

      }

      if?(e?>=?sSorted.get(sSorted.size?-?1))?{

      sSorted.add(e);

      return;

      }

      if?(e?<=?sSorted.get(0))?{

      sSorted.add(0,?e);

      return;

      }

      if?(sSorted.contains(e))?{

      sSorted.add(sSorted.indexOf(e),?e);

      return;

      }

      //?more...

      他想干什么呢?也許是優化性能吧,只能這么幫腔了。另外,他對size的理解,和數組的length相同。

      這位算是經驗比較豐富(30歲),對Java的理解比較深入的了。他說排序不需要手寫,Java里有現成的接口。我說,是這樣沒錯,但接口我沒給出,如果你記得,那就寫出來吧。

      于是他在剛才那一大段“優化”的后面,這么寫了:

      sSorted.add(e);

      sSorted.sort(new?Comp...able()?{

      public?boolean??(left,?right)?{

      return?right?>=?left;

      }

      });

      思路上,插入后再排序,我先不吐槽。我明明說了“記得”再寫,這Comparable及其接口int compareTo(T another)如果記不清,我就當看lambda表達式了。可是,他這個?分明是Comparator的int compare(T lhs, T rhs)接口呀!

      不過,其實這些我都可以捏著鼻子認了,因為我也手寫不出來。但List是沒有sort方法的呀!

      Arrays和Collections才有各自的sort方法,它倆算是銀彈型工具類,而Array和Collection是沒有的。這個細節,誰用誰知道,知道了就絕不會記錯,盡管就差一個s。

      還有一位,他先插入、再冒泡排序,是這么寫的:

      sSorted.add(e);

      for?(int?i?=?0,?sSorted.size(i)?>?sSorted.get(e),?i++)?{

      temp?=?sSorted.get(e);

      sSorted.get(e)?=?sSorted.size(i);

      sSorted.size(i)?=?temp;

      }

      你沒看錯,for()里面是,分隔的。

      你沒看錯,temp是從石頭縫里蹦出來的。

      你沒看錯,List.get(e)是可以對其賦值的。

      你沒看錯,List.size(i)是可以傳參數進去的。

      還有兩位,直接交白卷放棄了。

      其中一位還比較認真,思考了一會兒,說“我不想浪費時間”。

      我沒亂用詞,他確實“比較認真”。另一位在我遞過去后,直接看兩眼就遞回來,“排序我不會”,然后看手機去了。

      o(╯□╰)o

      參-

      我自己在紙上寫的時候,花了大概5分鐘去思考細節,再花5分鐘寫出來。(唉……一不小心,又暴露了自己奇慢無比的思維,以及奇慢無比的寫字速度。)這比我此前預計的時間多了好幾倍!

      不過,以我給的15~25分鐘,應該不算太難為人……吧?

      class?Solution?{

      private?static?List?sSorted?=?new?LinkedList<>();

      public?static?void?addElement(int?e)?{

      int?i;

      for?(i?=?0;?i?

      if?(e?<=?sSorted.get(i))?{

      break;

      }

      }

      sSorted.add(i,?e);

      }

      }

      這是我自己在紙上寫的答案。(如果有興趣,可以停在此處,考慮下這是否是最優算法。)

      @Override

      public?E?get(int?location)?{

      if?(location?>=?0?&&?location?

      Link?link?=?voidLink;

      if?(location?

      for?(int?i?=?0;?i?<=?location;?i++)?{

      link?=?link.next;

      }

      }?else?{

      按這些知識點來全面快速復習Java面試題

      for?(int?i?=?size;?i?>?location;?i--)?{

      link?=?link.previous;

      }

      }

      return?link.data;

      }

      throw?new?IndexOutOfBoundsException();

      }

      這是 java.util.LinkedList在Android(API 23)上的實現,而反編譯Oracle JDK 1.8的實現也大同小異。也就是說,我寫的答案雖然看似簡潔,但其最壞時間復雜度與先插入再排序也沒太大區別,都是O(n2)。

      終日打燕,反而被燕啄了眼!(暴露了真實水平。)

      我后來又寫了一個參-,算是勉強在臉上摸了些防曬霜。(大家有興趣可以想想為什么這是一個改進。當然,一定還有更好的方案。)

      class?Solution?{

      private?static?List?sSorted?=?new?LinkedList<>();

      public?static?void?addElement(int?e)?{

      int?i?=?0;

      for?(int?j?:?sSorted)?{

      if?(e?<=?j)?{

      break;

      }

      ++i;

      }

      sSorted.add(i,?e);

      }

      }

      (我沒有在提示列表中給出迭代器,結果自己也被晃過去了。)

      隱藏的殺手锏

      面試官在出題考察應聘者時,應聘者也在通過這道題考察這家公司。

      為了避免讓人覺得這家公司考題太簡單、工作內容太無趣、里面的員工(我)水平太低,我還準備了一些后續問題,由淺入深,作為殺手锏。

      為什么LinkedList可以賦值給List?

      考察多態(polymorphism)。

      為什么List要寫<>內的內容,而LinkedList<>()可以不寫?

      考察泛型(generic)。

      為什么List里面是Integer,但放進去和拿出來的都是int?

      (此處有坑,其實拿出來的還是Integer。)

      考察基本數據類型的自動裝箱、拆箱(auto boxing/unboxing)。

      如何在外面有多線程調用時,保證這個唯一的List的正確性?

      考察synchronized和volatile。

      如何在多線程狀態下的每一個線程,各保持一個獨立的List?

      考察ThreadLocal。

      (當然,還有一些和Android相關的問題。)

      我真心是沒想考算法,所以連算法復雜度的評估都沒打算問。實際情況是,我往往沒有機會問這些問題,因為沒幾個人寫出來。

      吐槽與建議

      首先,噴一下大學擴招……算了,不扯這么遠了。那兩位放棄做題的,一個是計算機學院的,一個是軟件工程學院的。排序寫不出來,竟然也是能畢業的!

      有兩位是某App的開發者。我把他們的App下載下來,發現了一堆bug后,本來想忍忍、就當沒看見、碼農何苦為難碼農,然后手機發熱、卡頓、滅屏后幾乎點亮不了(內存泄露吃光了RAM,導致系統進程沒有內存可用)。過了一陣最終好了,我查看耗電排行,運行10分鐘就高居榜首,耗了17%的電——我嚇得立刻卸載了。一個第三方App能把系統給卡成這樣,一般人還真做不到。

      還有兩位是“相關專業”的,非計算機、軟件工程專業,反而表現最佳,雖然還是沒寫出來。

      他們無一例外,都是在大學以外,又參加過某些Java、Android培訓的。這些培訓班的水平,可見一斑。問題倒不一定是培訓班的教學質量,而是這種大規模提供人才轉型服務的形式本身——這個世界上,本來就不是誰,都能當一個好碼農,哪怕工作要求只是復制粘貼。

      現在,很多碼農都戲稱自己是在“搬磚”、復制粘貼,但實際上程序員的工作不可能僅止于此。使用別人寫好的基本算法,參考別人的實現代碼,只是為了集中精力去解決抽象層次更高的業務問題。

      “我們不寫代碼,我們只做代碼的搬運工。”——萬萬不可把這句話當做信條。

      還有很多人,在沒有Demo的情況下,無論給多么詳細的API或其它資料,仍然無法寫代碼。他們只能在既有的基礎上,修修補補,無法憑空創作。

      我推薦三本Java的基礎書:

      《Java編程思想》(Think in Java)

      這本是最合適的Java語言入門書。其它很多語法書都是從C/C++的角度來講Java的變化,或者從C++的思路來討論Java怎么用,而這本書的英文名則直接告訴你,請用Java來思考、解決問題。

      《Effective Java》

      Java中有很多坑,Java中也有很多糖。如果沒有看過這本書,那么不知不覺就會犯很多大忌。

      《代碼整潔之道》(Clean Code)

      我是在獨立寫一個小項目的時候開始看的。看到一半時項目也寫到一半,頓時連代碼都不會寫了!每天都在寫自己看不下去的代碼,而不知道怎么寫能看得過眼的。加速看完后,重新開始會寫代碼。最終,項目后半部分的代碼,和前半部分完全不同,不像一個人寫的,我后來又重構了一遍。

      (為什么我不多推薦點書呢?一來,是我本人也沒看過多少,囧;二來,三本是極限,根據我的經驗,推薦三本可以讓人看一本,推薦三本以上,受眾一本也不會看。)

      我有一個朋友,也是一個前同事,好學如好色。他周末都在找一個大學教室看書,甚至有時請年假去教室看書。一本《Java編程思想》,逐行精讀三遍以上。工作經驗不足兩年,跳槽三次,現在在一家百億級上市公司,年薪三十萬,統率十人。

      究其原因,無非基礎知識扎實,口水噴死面試官爾。

      后記

      我作為一個面試別人的初哥,一心只想著自己喜歡的***……呃不,插入排序算法,給別人造成了不必要的麻煩,只能說抱歉了。

      和我一起面試的,還有一個負責文檔和規范的妹子(前面提到過的那個)。她也是有一票否決權的,而且用得比我更頻繁!

      我最多只給交白卷的,和那個耗電超恐怖的App,這幾個人直接否決。而這個妹子,考察對方的其它綜合能力。

      在實際工作中,她是需求的接口人,我們需要和她溝通,實現各方對我們團隊的需求。所以,只要她說一句“我和這個人難以溝通”,那么Boss基本上就直接拒絕了。

      下次我還是換一道更簡單的吧,碼農何苦為難碼農。

      本文轉載自微信公眾號【java學習之道】。

      面試題

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:《智能系統與技術叢書 深度學習實踐:基于Caffe的解析》—1.2深度學習工具簡介
      下一篇:MindSpore21天實戰營(4)使用ModelArts和YoloV3-DarkNet50預訓練模型實現籃球檢測
      相關文章
      亚洲尹人九九大色香蕉网站 | 亚洲婷婷在线视频| 人人狠狠综合久久亚洲婷婷| 国产亚洲美女精品久久久久| 亚洲AV无码专区在线电影成人| 亚洲乱码无限2021芒果| 激情内射亚洲一区二区三区| 亚洲国产精品不卡在线电影| 亚洲精品无码久久久久sm| 自拍偷自拍亚洲精品被多人伦好爽| 亚洲区不卡顿区在线观看| 亚洲精品线路一在线观看| 亚洲精品NV久久久久久久久久| 亚洲成?v人片天堂网无码| 亚洲国产精品丝袜在线观看| 亚洲VA综合VA国产产VA中| 亚洲欧洲日产国码一级毛片| 亚洲一区精品伊人久久伊人| 国产成人99久久亚洲综合精品| 国内精品99亚洲免费高清| 亚洲中文字幕无码不卡电影| 亚洲国产无套无码av电影| 国产AV无码专区亚洲AVJULIA| 久久精品国产亚洲AV麻豆~| 亚洲AV无码码潮喷在线观看 | 亚洲AV无码乱码国产麻豆| 亚洲成人激情在线| 亚洲国产女人aaa毛片在线| 亚洲天天在线日亚洲洲精| 亚洲精品456在线播放| 亚洲毛片基地4455ww| 亚洲国产av玩弄放荡人妇| 国产亚洲精品免费| 亚洲人成人无码网www电影首页| 亚洲动漫精品无码av天堂| 亚洲黄色在线观看网站| 精品久久久久久亚洲精品| 亚洲精华国产精华精华液网站| 国产亚洲午夜精品| 亚洲人成人网站色www| 亚洲精品自产拍在线观看动漫|