Alex explicou muito bem. Para aqueles que ainda não entenderam bem, espero que este exemplo ajude você a entender:
Vamos dizer que eu trabalho para o Google, na equipe do Chrome, e quero adicionar um recurso ao navegador que notifica o usuário se o url que ele inseriu é um URL malicioso. Portanto, tenho um conjunto de dados de cerca de 1 milhão de URLs maliciosos, sendo o tamanho deste arquivo em torno de 25 MB. Como o tamanho é muito grande (grande em comparação com o tamanho do navegador), armazeno esses dados em um servidor remoto.
Caso 1: uso uma função hash com uma tabela hash. Eu escolho uma função de hash eficiente e executo todos os 1 milhão de urls por meio da função de hash para obter as chaves de hash. Em seguida, faço uma tabela hash (uma matriz), onde a chave hash me daria o índice para colocar essa URL. Agora, depois de fazer o hash e preencher a tabela de hash, verifico seu tamanho. Eu armazenei todos os 1 milhão de URLs na tabela de hash junto com suas chaves. Portanto, o tamanho é de pelo menos 25 MB. Esta tabela hash, devido ao seu tamanho, será armazenada em um servidor remoto. Quando um usuário chega e insere um URL na barra de endereço, preciso verificar se é malicioso. Assim, executo o URL por meio da função hash (o próprio navegador pode fazer isso) e obtenho uma chave hash para esse URL. Agora tenho que fazer uma solicitação ao meu servidor remoto com essa chave hash, para verificar se o URL específico em minha tabela de hash com aquela chave específica é o mesmo que o usuário inseriu. Se sim, então é malicioso e se não, então não é malicioso. Assim, cada vez que o usuário insere um URL, uma solicitação ao servidor remoto deve ser feita para verificar se é um URL malicioso. Isso levaria muito tempo e, portanto, tornaria meu navegador lento.
Caso 2: Eu uso um filtro bloom. A lista inteira de 1 milhão de URLs é executada através do filtro bloom usando várias funções hash e as respectivas posições são marcadas como 1, em uma enorme matriz de 0s. Digamos que queremos uma taxa de falso positivo de 1%, usando uma calculadora de filtro bloom ( http://hur.st/bloomfilter?n=1000000&p=0.01), obtemos o tamanho do filtro bloom necessário como apenas 1,13 MB. Esse tamanho pequeno é esperado porque, embora o tamanho do array seja enorme, estamos armazenando apenas 1s ou 0s e não os URLs como no caso da tabela hash. Este array pode ser tratado como um array de bits. Ou seja, como temos apenas dois valores 1 e 0, podemos definir bits individuais em vez de bytes. Isso reduziria o espaço ocupado em 8 vezes. Este filtro bloom de 1,13 MB, devido ao seu tamanho pequeno, pode ser armazenado no próprio navegador da web !! Assim, quando um usuário chega e insere um URL, simplesmente aplicamos as funções hash necessárias (no próprio navegador) e verificamos todas as posições no filtro bloom (que está armazenado no navegador). Um valor de 0 em qualquer uma das posições nos diz que este URL NÃO ESTÁ DEFINITIVAMENTE na lista de URLs maliciosos e que o usuário pode proceder livremente. Portanto, não fizemos uma chamada para o servidor e, portanto, economizamos tempo. Um valor de 1 nos diz que o URL PODE estar na lista de URLs maliciosos. Nestes casos, fazemos uma chamada para o servidor remoto e lá podemos usar alguma outra função hash com alguma tabela hash como no primeiro caso para recuperar e verificar se a URL está realmente presente. Como, na maioria das vezes, um URL provavelmente não é malicioso, o pequeno filtro bloom no navegador descobre isso e, portanto, economiza tempo, evitando chamadas para o servidor remoto. Somente em alguns casos, se o filtro bloom nos diz que a URL PODE ser maliciosa, somente nesses casos fazemos uma chamada para o servidor. Esse 'MIGHT' está 99% certo. Nestes casos, fazemos uma chamada para o servidor remoto e lá podemos usar alguma outra função hash com alguma tabela hash como no primeiro caso para recuperar e verificar se a URL está realmente presente. Como, na maioria das vezes, um URL provavelmente não é malicioso, o pequeno filtro bloom no navegador descobre isso e, portanto, economiza tempo, evitando chamadas para o servidor remoto. Somente em alguns casos, se o filtro bloom nos diz que a URL PODE ser maliciosa, somente nesses casos fazemos uma chamada para o servidor. Esse 'MIGHT' está 99% certo. Nestes casos, fazemos uma chamada para o servidor remoto e lá podemos usar alguma outra função hash com alguma tabela hash como no primeiro caso para recuperar e verificar se a URL está realmente presente. Como, na maioria das vezes, um URL provavelmente não é malicioso, o pequeno filtro bloom no navegador descobre isso e, portanto, economiza tempo, evitando chamadas para o servidor remoto. Somente em alguns casos, se o filtro bloom nos diz que a URL PODE ser maliciosa, somente nesses casos fazemos uma chamada para o servidor. Esse 'MIGHT' está 99% certo. o pequeno filtro bloom no navegador descobre isso e, portanto, economiza tempo, evitando chamadas para o servidor remoto. Somente em alguns casos, se o filtro bloom nos diz que a URL PODE ser maliciosa, somente nesses casos fazemos uma chamada para o servidor. Esse 'MIGHT' está 99% certo. o pequeno filtro bloom no navegador descobre isso e, portanto, economiza tempo, evitando chamadas para o servidor remoto. Somente em alguns casos, se o filtro bloom nos diz que a URL PODE ser maliciosa, somente nesses casos fazemos uma chamada para o servidor. Esse 'MIGHT' está 99% certo.
Portanto, ao usar um pequeno filtro bloom no navegador, economizamos muito tempo, pois não precisamos fazer chamadas de servidor para cada URL inserido.
Podemos ver que a tabela hash com uma única função hash é usada para uma finalidade totalmente diferente de um filtro bloom. Espero que isso esclareça suas dúvidas :)
editar :
Implementei um filtro bloom para a tarefa de teste de URL malicioso em Python. O código pode ser encontrado aqui - https://github.com/tarunsharma1/Bloom-Filter
O código é muito simples de entender e uma descrição detalhada é fornecida no arquivo leia-me.