大數據研發相關-面試拾遺(備戰積累的知識點)


REST(representational state transfer) 接口開發 接口規范

冪等:無論操作多少次,請求的結果都是一樣的。
安全:訪問資源不會對資源發生修改。
POST的不冪等,應該被設計為用於提交修改。

接口 冪等 安全
POST × ×
GET
HEAD
DELETE ×
PUT ×

數據分箱的相關概念以及練習

等寬分箱:可以參考百度回答
800、 1000、 1200 、1500、 1500、 1800、 2000、 2300、 2500、 2800、 3000、 3500、 4000、 4500、 4800、 5000按照寬度為800進行分箱。
就是分為等區間的箱。

  1. 800、1000、1200、1500、1500
  2. 1800、2000、2300、2500
  3. 2800、3000、3500
  4. 4000、4500、4800
  5. 5000

K近鄰(KNN)

計算原理:
輸入不帶標簽的數據, 將其每個特征與樣本數據(帶標簽分類)對應的特征進行比較。計算新數據與樣本每一條數據的距離,對求得的所有距離進行排序。距離小的說明相似。取TopK,K個數據中出現最多的分類標簽作為新數據的分類。

決策樹

信息熵(香農熵):混亂程度
信息增益:划分數據集前后信息發生的變化。他等於前熵減去后熵,理解起來就是,添加一個特征之后,對於結果確定性的判斷影響了多少。信息增益越大,說明該信息越有用,表現為該特征是關鍵特征。
例子:明天有可能下雨,如果知道了明天陰天,那么下雨的不確定性就會降低很多。
優點:計算復雜度不高,輸出易理解。對中間的缺失值不敏感,可以處理不相關特征數據(就是說如果有一些特征對於結果的作用影響不大,那么他們也不會影響決策樹的准確構建,同樣的道理,我們也很容易知道哪些字段比較重要)。
缺點:難以預測連續的字段
類別較多時,錯誤增加的可能會比較快(過擬合)。

朴素貝葉斯

貝葉斯分類器,二分類c1、c2。數據是數值型或者bool型。條件概率。新數據(x,y),比較P(c1|x,y)和P(c2|x,y)
朴素貝葉斯基於兩個假設:特征獨立,並且特征同等重要
就文檔分類描述工作原理:
看不懂。。
算法特點:
優點:對少量數據也適用,可以處理多類別問題
缺點:輸入數據需要滿足數值型或者bool型,往往都需要進行數值轉化。
用途案例:社區侮辱性言論屏蔽。

java控制權限,編譯時控制,可以通過反射訪問私有成員,私有方法

關鍵字 類內 包內 子孫 包外
public
protected ×
default × ×
private × × ×

字符串的比較都是用equals比較,不用==

Integer和int的區別

null和0
一個是封裝的類,一個是基本數據類型
前者可以表達書未賦值和賦值為0的區別。int不能表達出未賦值的意思。

抽象類和普通類的區別:不能創建類的實例,允許有抽象方法。

java深拷貝和淺拷貝

深拷貝實現cloneable接口,重寫clone方法
實現徹底的深拷貝需要逐步重寫clone方法

內部類:

成員內部類 :類似於成員變量
方法內部類 :只能訪問方法中定義的final類型的變量
匿名內部類 :實際上也是方法內部類的一種。特點是只能實例化一次,而且沒有名字。需要繼承一個基類,但是不使用extends關鍵字。或是實現一個接口,也不使用implements關鍵字。

this.getClass().getName();

super.getClass().getName();
//兩句等效。

super.getClass().getName();
this.getClass().getSuperClass().getName();//這個才能獲取到父類的名字。因為getClass()方法是Object基類的一個final方法。super.getClass()和this.getClass()訪問的實際上都是Object的getClass()方法,是同一個。getClass()用於獲取當前運行類的名字。獲取父類需要用getSuperClass()

關於try{return;}catch{}finally{return;} try中返回只是將值存在函數棧,繼續執行finally中的return ,更新了值。之后返回控制權。

final finally finalize區別:

final關鍵字 用於修飾
finally總是執行 捕獲異常時使用
finalize是Object的一個方法。是垃圾回收期調用,用來回收資源使用的。可以重寫。

創建線程的兩種方式:

繼承Thread類:

MyThread mthread=new MyThread();
mthread.start();

實現Runable接口

MyThread mthread=new MyThread();
new Thread(mthread).start();

servlet

繼承HttpServlet
doGet(HttpServletRequest,HttpServletResponse)
生命周期

  1. init() 初始化
  2. service() 處理客戶端請求。檢查請求類型(put,get,post,delete)
  3. doXX 比如doGet,doPost..
  4. destory()

軟件開發模型

  1. 迭代模型

  2. 螺旋模型
    何時使用:大系統風險大,需求不明
    可以看做是每個階段都事先加了風險分析的快速原型模型。一圈一圈螺旋線。

  3. 增量模型

  4. 快速原型模型
    何時使用:需求不明確時
    特點:可以跟客戶進行全面的溝通,獲取更為詳細明確的需求和需求變化。原型開發簡單,周期短,經濟。
    過程見圖:

  5. 瀑布模型
    何時使用:大系統風險小
    特點:經典,老套;前一階段的輸出作為下一階段的輸入,順序性和依賴性;每個階段都要交付合格的文檔;如果用戶需求突然變更會很頭疼。
    過程: 可行性研究 ->需求分析->概要設計 ->詳細設計 ->編碼以及單元測試->測試

馮諾依曼體系結構

存儲器:存放數據和程序
控制器:控制指揮程序和數據的輸入運行,處理運算結果
運算器:完成算數運算和邏輯運算,並暫存中間結果
輸入:鍵盤,鼠標
輸出:顯示器

鏈接

線程池,說一下線程池工作原理,任務拒接策略有哪幾種

首先說一下線程池的意義:
執行一個任務的耗時,包含三個部分:T1創建線程,T2執行任務,T3銷毀線程。如果T1+T3的時間遠大於T2,那么創建並維護一個線程池來管理線程就很有必要了,對於提升服務性能有很大的幫助。重復利用閑置線程,盡量避免創建和銷毀線程的耗時操作。
常見線程池的類型:
newSingleThreadExecutor池中單線程工作
newFixedThreadExecutor池中的線程數固定。池滿,新任務則等待。
newCacheThreadExecutor重點在於,空閑線程超過固定時間之后,會被回收。當需要新的線程還會重新創建。
newScheduleThreadExecutor線程數無限。

java提供了一個java.util.concurrent.Executors工具類用於創建線程池。讀其源碼,可以看到它實際上是通過 ThreadPoolExecutor 在創建線程池。
看ThreadPoolExecutor的構造方法:

    public ThreadPoolExecutor(int corePoolSize,//即使沒有任務,依然存在的線程(等候任務的分配)。
                              int maximumPoolSize,//哪怕任務再多,也不能分配更多的線程(考慮機器性能有上限)
                              long keepAliveTime,//空轉線程(非核心線程)最長空轉時間,自動銷毀。
                              TimeUnit unit,//指定存活時間的單位
                              BlockingQueue<Runnable> workQueue,//提交的任務都在隊列中。阻塞隊列。隊列內的任務數存在上限。
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler//拒絕策略,當線程池滿了,並且隊列也是滿的時候,會調用,拒絕執行該任務。
                              ) {
        if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

任務提交執行流程:

        int c = ctl.get();
        if (workerCountOf(c) < corePoolSize) {//如果當前活躍線程數小於核心線程數,則可以直接創建線程執行任務(addworker())
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        if (isRunning(c) && workQueue.offer(command)) {//將任務添加到阻塞隊列,並且添加成功
            int recheck = ctl.get();//再次檢查
            if (! isRunning(recheck) && remove(command))
                reject(command);
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        else if (!addWorker(command, false))//添加到阻塞隊列失敗。執行拒絕策略
            reject(command);

總的來說:新任務到來,首先檢查當前活躍線程數是否小於核心線程數,小於,則獲取線程並執行任務,不小於,則再判斷阻塞隊列是否已滿,不滿,則添加任務入隊列等待執行,滿了,則判斷線程池是否滿了,如果未滿,則創建線程執行任務,滿了則拒絕任務執行。
拒絕策略的種類(內置四種):

  1. discardpolicy 直接拋棄,不執行任務
  2. DiscardOldestPolicy 拋出隊列中最老的任務,並嘗試重新運行剛提交的任務
  3. abortpolicy(默認) 不執行任務並拋出異常RejectedExecutionException。需要try catch。
  4. callerRunspolicy 線程池沒有資源了,本來想讓別人幫忙干活的,現在只能自己干了。會造成當前線程的阻塞。

進程和線程的區別

我們寫的代碼,都可以稱為是一個程序,一個程序的運行,至少需要一個進程,一個進程至少需要一個線程。
多個進程之間有獨立的內存單元,互不干擾,而線程之間共享內存。所以就會有經常遇到的線程安全,同步等問題。
進程是系統進行資源分配和資源調度的一個獨立單位。
線程是CPU進行調度和分配的單位。

線程同步的方式有哪些?

事務的四大特性ACID

A:原子性。事務中所有的操作要么成功,要么全部失敗回滾到操作之前。
C:一致性。事務必須要使數據庫從一個一致性狀態轉到另一個一致性狀態。怎么理解這個一致性?比如說轉賬,兩個人的總額是10000,不管怎么來回轉,最終的操作結果必定滿足總額還是10000.
I:isolation隔離性。事務的操作不會被外界操作或者別的事務操作所影響。特別是在遭遇並發的時候,事務的隔離級別參考下面。
D:持久性。事務一旦提交,作出的更改就是永久性的。

事務的隔離級別

如果沒有事務隔離性,會發生以下情況:
臟讀:舉個例子,A向B轉賬。A的所有操作都在一個事務中,事務中包含兩個操作+100和-100。在+100之后,事務暫未提交,此時B那邊查賬會發現確實有100轉進來,而當A提交事務之后,-100執行。B再查賬會發現余額為0。所謂臟讀,就是一個事務中讀取了另一個未提交的事務的數據。
不可重復讀:見下面一段話。
幻讀:見下。
幻讀和不可重復讀都是讀取了已經提交的事務數據。臟讀讀取的是未提交的事務數據。不可重復讀針對的hi同一個數據項,兩次讀取的結果不一樣。幻讀是針對一批數據,事務A提交了修改,同時事務B也提交了修改,但是如果此時A再查詢的話,會發現,“咦,我明明已經完成修改了,怎么還有不符合我修改之后的數據項啊?”實際上這是事務B在搗鬼。
Serializable串行化:隔離最高。同時避免三種錯誤。
Repeatable read可重復讀:可以避免臟讀和不可重復讀。
Read committed讀已提交(讀取的數據是已經提交的):可以避免臟讀。(常見的默認隔離級別)
Read unconmmited讀未提交(會發生讀取未提交的數據):隔離最低
請在事務開啟之前,設置隔離級別

mysql>set transaction isolation level repeatable read;//設置隔離級別
mysql>select @@tx_isolation;//查詢當前隔離級別

Hive的特點說一下

Hive是基於hdfs建立的數據倉庫, 將數據文件存成一張表,稱為元數據, 記錄表的所屬的數據庫, 表的字段等信息。 具有類似sql的查詢功能,面對較大的數據查詢,其將sql自動轉為MR的操作可以充分利用集群的計算資源進行查詢,自動轉化,不用另行編寫MR代碼。

JVM研究

GC部分

類加載部分

java類裝載到JVM中有兩種方式,隱式裝載(比如new對象的時候),顯式裝載。
常用以下有四種classLoader

  1. BootStrap ClassLoader 引導類加載器 主要用於加載 /jre/lib、/jre/classes目錄下的核心類庫。這是最頂層的一個加載器,使用C++編寫的。
  2. Extention ClassLoader 擴展類加載器 負責加載/JAVA_HOME/lib/ext/類庫
  3. Application ClassLoader 應用類加載器 主要負責加載CLASSPATH下的類庫和我們自己的java代碼編譯出來的class文件。
    除了引導加載器獲取不到外(因為是用C++寫的),其他的加載器我們都能通過代碼查詢到。
  4. 自定義加載器 需要繼承classloader類
public class Test_ClassLoader {
    public static void main(String[] args){
        System.out.println(Test_ClassLoader.class.getClassLoader());
        System.out.println(Test_ClassLoader.class.getClassLoader().getParent());
        System.out.println(Test_ClassLoader.class.getClassLoader().getParent().getParent());
    }
}
outout:
sun.misc.Launcher$AppClassLoader@58644d46
sun.misc.Launcher$ExtClassLoader@4554617c
null
Process finished with exit code 0

一份java源碼從產生到被運行的流程
0. 首先.java文件只有編譯成class字節碼文件之后才能被類加載器讀取,加載到JVM中。

  1. 檢查類是否被加載,從上往下找。
  2. 裝載:導入class文件
  3. 檢查文件的是否有錯,分析文件,給靜態變量分配空間。
  4. 初始化,主要是靜態變量,靜態代碼塊的初始化

=====================
我的其他相關文章:

  1. Hive知識匯總
  2. 大數據研發相關-面試拾遺(備戰積累的知識點)
  3. 2018年春招面試實戰記錄-大數據開發相關崗位
  4. HadoopMR-Spark-HBase-Hive

歡迎關注微信公眾號“IT客“


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM