哈希表
package edu.pdsu.map;
/**
手写HashMap集合的put和get方法
*/
public class MyHashMap<K,V> {
//用于存放链表
private Node<K,V>[] table;
//键值对的个数
private int size;
@SuppressWarnings("unchecked")
public MyHashMap() {
//注意:数组在new的时候不能添加泛型
//创建一个空数组,长度为16
this.table = new Node[16];
}
//节点内部类
static class Node<K,V>{
//哈希值
int hash;
//key
K key;
//value
V value;
//下一个节点
Node<K,V> next;
//构造方法
public Node(int hash, K key, V value, Node<K, V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
@Override
public String toString() {
return "["+key+","+value+"]";
}
}
//返回键值对的个数
public int getSize() {
return size;
}
//添加元素,未覆盖时返回的添加value,覆盖时返回原先的value
public V put(K key,V value){
//特判处理key为null的情况
if (key == null) {
//放到索引处为0的地方
return putForNullKey(value);
}
//key不是null
//首先通过key计算出哈希码
int hashCode = key.hashCode();//有可能是负数
int index = Math.abs(hashCode % table.length);//取模的值一定是0到数组长度的值
//准备存入
Node<K, V> node = table[index];
if (null == node){//常量值往前写,是一种小技巧
//当前索引处为空
table[index] = new Node<>(hashCode,key,value,null);
size++;
return value;
}
//执行到这里说明有元素,已经变成单向列表了
//开始遍历之前,先定义最后一个节点
Node<K,V> preNode = null;
while (null != node) {
//查看是否有重复的
if (node.key == key) {
V oldValue = node.value;
node.value = value;
return oldValue;
}
//找到最后一个节点
preNode = node;
node = node.next;
}
preNode.next = new Node<>(hashCode,key,value,null);
size++;
return value;
}
private V putForNullKey(V value) {
//插入前也要特判,取出头节点
Node<K,V> node = table[0];
if (node == null) {
table[0] = new Node<>(0,null,value,null);
size++;
return value;
}
//说明索引处为0的地方已经有元素了,已经是一个单向链表了
//要开始遍历了,遍历时要保留住最后一个节点
Node<K,V> preNode = null;
while (node != null) {
//开始一直向下指
if (node.key == null) {
V oldValue = node.value;
//说明已经有这个key了
//覆盖
node.value = value;
return oldValue;
}
//最后一次循环时preNode为尾节点
preNode = node;
//这个node为null
node = node.next;
}
//让最后一个节点指向新增节点
preNode.next = new Node<>(0,null,value,null);
size++;
return value;
}
//通过key返回value
public V get(K key){
//对key为null时进行特判
if (null == key) {
return getForNullKey();
}
//key不是空
//首先算出哈希码,然后算出下标
int hashCode = key.hashCode();
int index = Math.abs(hashCode % table.length);
Node<K, V> node = table[index];
if (null == node){
//代表key不存在
return null;
}
//key存在,单向链表也存在
while (null != node) {
if (node.key.equals(key)){
return node.value;
}
node = node.next;
}
return null;
}
private V getForNullKey() {
Node<K, V> node = table[0];
if (null == node) {
//数组下标为0的位置为空
return null;
}
//数组为0的位置是单向链表
while (null != node.next) {
if (null == node.key){
//找到了
return node.value;
}
node = node.next;
}
return null;
}
//输出每一个节点
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < table.length; i++) {
Node<K,V> node = table[i];
if (node != null) {
//遍历节点
while (node != null) {
sb.append(node);
sb.append(",");
node = node.next;
}
sb.append("\n");
}
}
return sb.toString();
}
}
测试类
package edu.pdsu.map;
import org.junit.Test;
public class MyHashMapMethodTest {
private static MyHashMap<String,String> map = new MyHashMap<>();
@Test
public void testPut(){
map.put("114514","蔡徐坤");
map.put("114514","鸡哥");
map.put("211053","陈立农");
map.put("3331456","范丞丞");
map.put("466566","黄明浩");
map.put(null,"哇真的是你啊");
System.out.println(map);
//[null,哇真的是你啊]
//[466566,黄明浩]
//[114514,鸡哥]
//[3331456,范丞丞]
//[211053,陈立农]
}
@Test
public void testGet(){
map.put("114514","蔡徐坤");
map.put("114514","鸡哥");
map.put("211053","陈立农");
map.put("3331456","范丞丞");
map.put("466566","黄明浩");
map.put(null,"哇真的是你啊");
String s = map.get("114514");
System.out.println(s);//鸡哥
}
}