哈希
基本概念
若关键字为k,则其值存放在F(k)的存储位置上。由此,不需要比较便可直接取得所查记录。称这个对应关系F为散列函数,按这个思想建立 的表称为散列表。
存在F(k1)=F(k2)称为冲突,java中用来处理冲突的方法为拉链法(Java源码的hashmap功能强大的多:可根据负载因子自动扩容,处理冲突的方法多)
关于map,set
存入Set的每个元素都必须是唯一的,因为Set不保存重复元素。加入Set的元素必须定义equals()方法以确保对象的唯一性。Set与Collection有完全一样的接口。Set接口不保证维护元素的次序。
HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。比hashmap的时间复杂度要快,相当于最佳情况的hashmap(“桶”中只有一个元素)
TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。
LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示
代码实现
见文末(hashset基于hashmap实现)
布隆过滤器
应用海量数据对比。原理:当一个元素被加入集合时,通过k个散列函数将这个元素映射成一个位数组中的k个点,并把他们置为1.检索时,通过hash函数计算得出为1的点,只要看这些点在原先的数组中是不是1即可大约判断,若存在一个是0就一定不存在。
一致性hash
应用于服务器集群
hashmap代码
package com.dataStructure.hash;
import java.util.Iterator;
public class MyHashMap<K, V> implements IMap<K, V> {
private int length = 16;
private Node[] buckets = new Node[length];
private int size;
@Override
public void clear() {
for (int i = 0; i < buckets.length; i++) {
buckets[i] = null;
}
}
@Override
public boolean containsKey(K key) {
int index = hash1(key);
if(buckets[index] == null){
return false;
}else {
Node<K, V> p = buckets[index];
while(p != null){
K k1 = p.key;
if(k1 == key || (k1.hashCode() == key.hashCode() && k1.equals(key))){
return true;
}
p = p.next;
}
}
return false;
}
@Override
public boolean containsValue(V value) {
for (int i = 0; i < buckets.length; i++) {
if(buckets[i] != null){
Node<K, V> p = buckets[i];
while(p != null){
if (p.value.equals(value)) {
return true;
}
p = p.next;
}
}
}
return false;
}
@Override
public V get(K key) {
int index = hash1(key);
if(buckets[index] == null){
return null;
}
Node<K, V> p = buckets[index];
while(p != null){
K k1 = p.key;
if (k1 == key || (p.key.equals(key) && k1.hashCode() == key.hashCode())) {
return p.value;
}
p = p.next;
}
return null;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void put(K key, V value) {
Node<K, V> node = new Node<>(key, value);
int index = hash1(key);
Node<K, V> p = buckets[index];
if(buckets[index] == null){
buckets[index] = node;
size++;
}else {
while(p!=null){
K k1 = p.key;
if(k1 == key || (k1.equals(key) && k1.hashCode() == key.hashCode())){
p.value = value;
break;
}
if(p == null){
p.next = node;
size++;
break;
}
p = p.next;
}
}
}
@Override
public void putAll(IMap<? extends K, ? extends V> map) {
// TODO Auto-generated method stub
}
@Override
public V remove(K key) {
int index = hash1(key);
if(buckets[index] == null){
return null;
}
Node<K, V> p = buckets[index];
Node<K, V> pre = p;
while(p != null){
K k1 = p.key;
if(k1 == p.key || (k1.equals(key) && k1.hashCode() == key.hashCode())){
if(p == pre){
buckets[index] = pre.next;
}else {
pre.next = p.next;
}
p = p.next;
size--;
return pre.value;
}
pre = p;
p = p.next;
}
return null;
}
@Override
public int size() {
return size;
}
@Override
public V[] values() {
// TODO Auto-generated method stub
return null;
}
/**
* 哈希算法
* @param key
* @return
*/
private int hash1(K key) {
// return key.hashCode() % length;
int h = 0;
int seed = 31;//素数
String s = key.toString();
for (int i = 0; i != s.length(); ++i) {
h = seed * h + s.charAt(i);
}
return h % length;
}
/**
* 节点
* @author Myth
*
* @param <K>
* @param <V>
*/
public class Node<K, V>{
public K key;
public V value;
public Node(K key, V value){
this.key = key;
this.value = value;
}
private Node next;
@Override
public String toString() {
return "Node [key=" + key + ", value=" + value + "]";
}
}
@Override
public Iterator<Node> iterator() {
return new MapInterator();
}
private class MapInterator implements Iterator<Node> {
int i = 0;
Node p = buckets[0];
@Override
public boolean hasNext() {
while (this.i < length && p == null) {
this.i++;
if (this.i == length)
p = null;
else
p = buckets[this.i];
}
//i是一个非空的桶,p是链表头
return p != null;
}
@Override
public Node next() {
Node res = p;
p = p.next;
return res;
}
@Override
public void remove() {
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < buckets.length; i++) {
if (buckets[i] != null) {
Node<K, V> p = buckets[i];
while (p != null) {
sb.append("(" + p.key + "," + p.value + "),");
p = p.next;
}
}
}
return sb.toString();
}
}
hashset代码
package com.dataStructure.hash;
import java.util.Iterator;
public class MyHashSet<E> implements IHashSet<E> {
private MyHashMap<E, E> map = new MyHashMap<>();
@Override
public void add(E key) {
map.put(key, null);
}
@Override
public void remove(E key) {
map.remove(key);
}
@Override
public void clear() {
map.clear();
}
@Override
public boolean contains(E key) {
return map.containsKey(key);
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public int size() {
return map.size();
}
@Override
public Iterator<E> iterator() {
final Iterator<MyHashMap.Node> iter = map.iterator();
return new Iterator<E>() {
@Override
public boolean hasNext() {
return iter.hasNext();
}
@Override
public E next() {
return (E) iter.next().key;
}
@Override
public void remove() {
}
};
}
@Override
public String toString() {
Iterator<MyHashMap.Node> iter = map.iterator();
StringBuilder sb = new StringBuilder();
while(iter.hasNext()){
sb.append("{"+iter.next().key+",");
}
return sb.toString();
}
}