【直通BAT】海量數據面試總結

目錄java

  • 海量數據計算總結node

  • 海量數據去重總結python

1. 計算容量

在解決問題以前,要先計算一下海量數據須要佔多大的容量。常見的單位換算以下:程序員

  • 1 byte = 8 bit面試

  • 1 KB = 210 byte = 1024 byte ≈ 103 byte數組

  • 1 MB = 220 byte ≈ 10 6 byteide

  • 1 GB = 230 byte ≈ 10 9 byte函數

  • 1 億 = 108oop

1 個整數佔 4 byte,1 億個整數佔 4*108 byte ≈ 400 MB。學習

2. 拆分

能夠將海量數據拆分到多臺機器上和拆分到多個文件上:

  • 若是數據量很大,沒法放在一臺機器上,就將數據拆分到多臺機器上。這種方式可讓多臺機器一塊兒合做,從而使得問題的求解更加快速。可是也會致使系統更加複雜,並且須要考慮系統故障等問題;

  • 若是在程序運行時沒法直接加載一個大文件到內存中,就將大文件拆分紅小文件,分別對每一個小文件進行求解。

有如下策略進行拆分:

  • 按出現的順序拆分:當有新數據到達時,先放進當前機器,填滿以後再將數據放到新增的機器上。這種方法的優勢是充分利用系統的資源,由於每臺機器都會盡量被填滿。缺點是須要一個查找表來保存數據到機器的映射,查找表可能會很是複雜而且很是大。

  • 按散列值拆分:選取數據的主鍵 key,而後經過哈希取模 hash(key)%N 獲得該數據應該拆分到的機器編號,其中 N 是機器的數量。優勢是不須要使用查找表,缺點是可能會致使一臺機器存儲的數據過多,甚至超出它的最大容量。

  • 按數據的實際含義拆分:例如一個社交網站系統,來自同一個地區的用戶更有可能成爲朋友,若是讓同一個地區的用戶儘量存儲在同一個機器上,那麼在查找一個用戶的好友信息時,就能夠避免到多臺機器上查找,從而下降延遲。缺點一樣是須要使用查找表。

3. 整合

拆分以後的結果還只是局部結果,須要將局部結果彙總爲總體的結果。

注:大部分海量數據均可以使用hash取模來處理,由於同一個值hash取模後必定會分配到同一個位置。若是內存實在小,N的值能夠取大一些。再者,Hadoop和spark也是處理海量數據的方案,不過非大數據方向應該不作要求。


下面是海量數據去重問題:

1. 問題描述

對於海量數據,要求判斷一個數據是否已經存在。這個數據頗有多是字符串,例如 URL。

2. HashSet

最直觀的方法是使用 HashSet 存儲,那麼就能以 O(1) 的時間複雜度判斷一個數據是否已經存在。

考慮到數據是海量的,那麼就須要使用拆分的方式將數據拆分到多臺機器上,分別在每臺機器上使用 HashSet 存儲。咱們須要使得相同的數據拆分到相同的機器上,可使用哈希取模的拆分方式進行實現。

3. BitSet

若是海量數據是整數,而且範圍不大時,就可使用 BitSet 存儲。經過構建必定大小的比特數組,而且讓每一個整數都映射到這個比特數組上,就能夠很容易地知道某個整數是否已經存在。由於比特數組比整型數組小的多,因此一般狀況下單機就能處理海量數據。

如下是一個 BitSet 的實現,固然在實際開發中能夠直接使用語言內置的實現。

class BitSet {
    int[] bitset;

    public BitSet(int size) {
        bitset = new int[(size >> 5) + 1]; // divide by 32
    }

    boolean get(int pos) {
        int wordNumber = (pos >> 5); // divide by 32
        int bitNumber = (pos & 0x1F); // mod 32
        return (bitset[wordNumber] & (1 << bitNumber)) != 0;
    }

    void set(int pos) {
        int wordNumber = (pos >> 5); // divide by 32
        int bitNumber = (pos & 0x1F); // mod 32
        bitset[wordNumber] |= 1 << bitNumber;
    }
}
複製代碼

使用 BitSet 還能夠很容易地解決一個整數出現次數的問題,例如使用兩個比特數組就能夠存儲 0~3 的信息。其實判重問題也能夠簡單當作一個數據出現的次數是否爲 1,所以一個比特數組就夠了。

4. 布隆過濾器

布隆過濾器可以以極小的空間開銷解決海量數據判重問題,可是會有必定的誤判機率。它主要用在網頁黑名單系統、垃圾郵件過濾系統、爬蟲的網址判重系統。

布隆過濾器也是使用 BitSet 存儲數據,可是它進行了必定的改進,從而解除了 BitSet 要求數據的範圍不大的限制。在存儲時,它要求數據先通過 k 個哈希函獲得 k 個位置,並將 BitSet 中對應位置設置爲 1。在查找時,也須要先通過 k 個哈希函數獲得 k 個位置,若是全部位置上都爲 1,那麼表示這個數據存在。

因爲哈希函數的特色,兩個不一樣的數經過哈希函數獲得的值可能相同。若是兩個數經過 k 個哈希函數獲得的值都相同,那麼使用布隆過濾器會將這兩個數判爲相同。

能夠知道,令 k 和 m 都大一些會使得誤判率下降,可是這會帶來更高的時間和空間開銷。

布隆過濾器會誤判,也就是將一個不存在的數判斷爲已經存在,這會形成必定的問題。例如在垃圾郵件過濾系統中,會將一個郵件誤判爲垃圾郵件,那麼就收不到這個郵件。可使用白名單的方式進行補救。

5. Trie

Trie 樹又叫又叫字典樹、前綴樹、單詞查找樹,它是一顆多叉查找樹。與二叉查找樹不一樣,鍵不是直接保存在節點中,而是由節點在樹中的位置決定。

若是海量數據是字符串數據,那麼就能夠用很小的空間開銷構建一顆 Trie 樹,空間開銷和樹高有關。

Leetcode : Implement Trie (Prefix Tree)

class Trie {
    private class Node {
        Node[] childs = new Node[26];
        boolean isLeaf;
    }

    private Node root = new Node();

    public Trie() {
    }

    public void insert(String word) {
        insert(word, root);
    }

    private void insert(String word, Node node) {
        if (node == null) return;
        if (word.length() == 0) {
            node.isLeaf = true;
            return;
        }
        int index = indexForChar(word.charAt(0));
        if (node.childs[index] == null) {
            node.childs[index] = new Node();
        }
        insert(word.substring(1), node.childs[index]);
    }

    public boolean search(String word) {
        return search(word, root);
    }

    private boolean search(String word, Node node) {
        if (node == null) return false;
        if (word.length() == 0) return node.isLeaf;
        int index = indexForChar(word.charAt(0));
        return search(word.substring(1), node.childs[index]);
    }

    public boolean startsWith(String prefix) {
        return startWith(prefix, root);
    }

    private boolean startWith(String prefix, Node node) {
        if (node == null) return false;
        if (prefix.length() == 0) return true;
        int index = indexForChar(prefix.charAt(0));
        return startWith(prefix.substring(1), node.childs[index]);
    }

    private int indexForChar(char c) {
        return c - 'a';
    }
}
複製代碼

參考資料

  • Bloom Filters: Is element x in set S?

  • 程序員面試金典

  • 程序員代碼面試指南

推薦閱讀

☞【直通BAT】一篇文章搞定java容器面試

資料分享

java學習筆記、10T資料、100多個java項目分享


歡迎關注我的公衆號【菜鳥名企夢】,公衆號專一:互聯網求職面經javapython爬蟲大數據等技術分享**: 公衆號**菜鳥名企夢後臺發送「csdn」便可免費領取【csdn】和【百度文庫】下載服務; 公衆號菜鳥名企夢後臺發送「資料」:便可領取5T精品學習資料**、java面試考點java面經總結,以及幾十個java、大數據項目資料很全,你想找的幾乎都有

掃碼關注,及時獲取更多精彩內容。(博主今日頭條大數據工程師)
相關文章
相關標籤/搜索