返回

海量数据操作之利刃——分治、哈希、位图、布隆过滤器、堆解析

后端

掌控海量数据:分治算法、哈希、位图、布隆过滤器和堆的利器

前言

在这个数字化的时代,海量数据无处不在,给 IT 从业者带来了不小的挑战。如何处理、存储、分析这些庞然大物?别担心!我们有强大的算法,助你轻松应对海量数据难题。

分治算法:庖丁解牛,分而治之

分治算法是解决海量数据问题的首选武器。它将一个复杂的问题分解成多个更小、更易处理的子问题,再逐个解决,最终合并子问题的解得到原问题的解。分治算法的典型代表莫过于"快速排序"和"归并排序",凭借其卓越的性能,它们在海量数据排序领域独领风骚。

代码示例:快速排序

public static void quickSort(int[] arr, int low, int high) {
    if (low < high) {
        int partitionIndex = partition(arr, low, high);

        quickSort(arr, low, partitionIndex - 1);
        quickSort(arr, partitionIndex + 1, high);
    }
}

private static int partition(int[] arr, int low, int high) {
    int pivot = arr[high];
    int i = (low - 1);

    for (int j = low; j <= high - 1; j++) {
        if (arr[j] < pivot) {
            i++;

            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

    int temp = arr[i + 1];
    arr[i + 1] = arr[high];
    arr[high] = temp;

    return (i + 1);
}

哈希:化繁为简,妙笔生花

哈希算法堪称数据存储领域的魔法师。它利用哈希函数将数据映射到一个固定长度的输出中,称为哈希值。哈希函数的设计巧妙之处在于,相似的数据往往会产生相同的哈希值,从而让数据查找变得异常高效。哈希算法在海量数据存储中扮演着不可或缺的角色,如数据库索引、缓存系统等。

代码示例:哈希表

public class MyHashMap<K, V> {
    private Entry<K, V>[] table;
    private int size;

    public MyHashMap() {
        this(16);
    }

    public MyHashMap(int capacity) {
        table = new Entry[capacity];
        size = 0;
    }

    public void put(K key, V value) {
        int index = hash(key);
        Entry<K, V> newEntry = new Entry<>(key, value);

        if (table[index] == null) {
            table[index] = newEntry;
        } else {
            Entry<K, V> current = table[index];
            while (current.next != null) {
                current = current.next;
            }

            current.next = newEntry;
        }

        size++;
    }

    public V get(K key) {
        int index = hash(key);

        if (table[index] == null) {
            return null;
        } else {
            Entry<K, V> current = table[index];

            while (current != null) {
                if (current.key.equals(key)) {
                    return current.value;
                }

                current = current.next;
            }
        }

        return null;
    }

    private int hash(K key) {
        return key.hashCode() % table.length;
    }

    private class Entry<K, V> {
        K key;
        V value;
        Entry<K, V> next;

        public Entry(K key, V value) {
            this.key = key;
            this.value = value;
            this.next = null;
        }
    }
}

位图:黑白分明,一目了然

位图,又名比特图,本质上是一个由位(bit)组成的数组。每个位代表一个元素,0表示不存在,1表示存在。位图的精妙之处在于,它能以极低的存储空间存储海量数据,同时提供超快的查询速度。位图在海量数据统计、日志分析、基因组分析等领域大放异彩。

代码示例:位图

public class MyBitSet {
    private long[] bits;
    private int size;

    public MyBitSet(int size) {
        this.size = size;
        bits = new long[(size + 63) / 64];
    }

    public void set(int index) {
        int wordIndex = index / 64;
        int bitIndex = index % 64;

        bits[wordIndex] |= (1L << bitIndex);
    }

    public boolean get(int index) {
        int wordIndex = index / 64;
        int bitIndex = index % 64;

        return (bits[wordIndex] & (1L << bitIndex)) != 0;
    }
}

布隆过滤器:海纳百川,有容乃大

布隆过滤器是一种概率型数据结构,旨在快速判断一个元素是否在一个集合中。它使用一系列哈希函数将元素映射到一系列位,如果所有哈希函数对应的位都为1,则该元素一定在集合中;如果有一个哈希函数对应的位为0,则该元素一定不在集合中。布隆过滤器在海量数据过滤、恶意软件检测、网页去重等领域备受青睐。

代码示例:布隆过滤器

public class MyBloomFilter {
    private int[] bits;
    private int size;
    private int numHashFunctions;

    public MyBloomFilter(int size, int numHashFunctions) {
        this.size = size;
        this.numHashFunctions = numHashFunctions;
        bits = new int[(size + 31) / 32];
    }

    public void add(String element) {
        for (int i = 0; i < numHashFunctions; i++) {
            int hashValue = hash(element, i);
            int wordIndex = hashValue / 32;
            int bitIndex = hashValue % 32;

            bits[wordIndex] |= (1 << bitIndex);
        }
    }

    public boolean contains(String element) {
        for (int i = 0; i < numHashFunctions; i++) {
            int hashValue = hash(element, i);
            int wordIndex = hashValue / 32;
            int bitIndex = hashValue % 32;

            if ((bits[wordIndex] & (1 << bitIndex)) == 0) {
                return false;
            }
        }

        return true;
    }

    private int hash(String element, int index) {
        return Math.abs(element.hashCode() + index) % size;
    }
}

堆:层层递进,井然有序

堆是一种特殊的树形数据结构,它满足堆性质:每个节点的值都大于或等于其子节点的值。堆的优势在于,它可以快速找到最大或最小的元素,时间复杂度为O(logn)。堆在海量数据排序、优先级队列、最短路径算法等领域发挥着举足轻重的作用。

代码示例:二叉堆

public class MyBinaryHeap {
    private int[] heap;
    private int size;

    public MyBinaryHeap(int capacity) {
        heap = new int[capacity + 1];
        size = 0;
    }

    public void insert(int value) {
        if (size == heap.length - 1) {
            expandHeap();
        }

        heap[++size] = value;
        heapifyUp(size);
    }

    public int extractMin() {
        if (size == 0) {
            throw new RuntimeException("Heap is empty!");
        }

        int min = heap[1];
        heap[1] = heap[size];
        size--;
        heapifyDown(1);

        return min;
    }

    private void heapifyUp(int index) {
        int parentIndex = index / 2;

        while (index > 1 && heap[index] < heap[parentIndex]) {
            swap(index, parentIndex);
            index = parentIndex;
            parentIndex = index / 2;
        }
    }

    private void heapifyDown(int index) {
        int leftIndex = 2 * index;
        int rightIndex = 2 * index + 1;
        int