哈希表:

   即散列存储结构。

散列法存储的基本思想:
   建立关键码字与其存储位置的对应关系,或者说,由关键码的值决定数据的存储地址。

链地址法(拉链法)处理冲突:
   基本思想:将具有相同哈希地址的记录链成一个单链表,m个哈希地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构。
在这里插入图片描述
实现:

class Node<T>
{
	public int key;
	public T value;
	public Node<T> next;
	public Node(int key,T value)
	{
		this.key=key;
		this.value=value;
		this.next=null;
	}
}

public class MyHash<T>
{
	private Node<T>[] buckets;
	private Node node;
	
	public MyHash()
	{
		this.buckets=(Node<T>[])new Object[10]; 
	}
	public MyHash(int size)
	{
		this.buckets=(Node<T>[])new Object[size]; 
	}
	//覆盖相同key
	public boolean replaceAttribute(int key, T value)
	{
		int index=key%this.buckets.length;   //确认数组索引位置
		Node<T> p=this.buckets[index];    //获得头指针
		while(p!=null)
		{
		   if(p.key==key) break;    //key重复
		   p=p.next;
		}
		if(p!=null){  p.value=value; return true;} //相同key,就进行覆盖
		return false;
	}
	//加入节点
	public boolean addAttribute(int key, T value)
	{
		int index=key%this.buckets.length;
		Node<T> p=this.buckets[index];      //获得头指针
		while(p!=null)
		{
		   if(p.key==key) break;    //key重复
		   p=p.next;
		}
		if(p!=null) return false;    //由break退出循环,则key重复,加入失败
		p=new Node<T>(key,value);
	    p.next=this.buckets[index];  //头插法插入节点
	    this.buckets[index]=p;
	    return true;
	}
	//获得关键字对应值
	public T  getAttribute(int key)
	{
		int index=key%this.buckets.length;
		Node<T> p=this.buckets[index];  //获得头指针
		Node<T> q=null;
		while(p!=null)
		{
		   if(p.key==key) break;   //得到key对应的节点p
		   q=p;
		   p=p.next;
		}
		if(p==null) return null;    //key不在表中,搜索失败
		if(p==this.buckets[index])  //p为头指针,删除p后则下一节点为头节点
			this.buckets[index]=p.next;
		else
		{
			q.next=p.next;     //将p删除
		}
		return p.value;
	}
	
}