Hash详解+java实现Hashmap Hashset

哈希

基本概念

若关键字为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();
	}
	
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值