Java实现Hash表

本文介绍了一个简单的自定义HashSet实现过程,包括内部节点的数据结构、基本的增删查操作及哈希算法的应用。通过实例演示了如何添加元素、检查元素存在性及移除元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class Node{//节点数据结构
private Object value;//节点的值
private Node next;//链表中指向下一结点的引用
/*提供了常见的操作*/
public Node(Object value){this.value = value;};
public Object getValue() {return value;}
public Node getNext() {return next;}
public void setNext(Node next){this.next=next;}
}

public class MyHashSet {//Hash数据结构
private Node[] array;//存储数据链表的数组
private int size = 0;//表示集合中存放的对象的数目
public MyHashSet(int length){
array = new Node[length];//创建数组
}
public int size(){return size;}
private static int hash (Object o){ //根据对象的哈希码得到一个优化的哈希码,
//算法参照java.util.HashMap的hash()方法
int h = o.hashCode();
h += ~(h<<9);
h ^= (h>>>14);
h += (h<<4);
h ^= (h>>>10);
return h;
}
private int indexFor(int hashCode){ //根据Hash码得到其索引位置
//算法参照java.util.HashMap的indexFor()方法
return hashCode & (array.length-1);
}
public void add(Object value) {//把对象加入集合,不允许加入重复的元素
int index = indexFor(hash(value));//先根据value得到index
System.out.println("index:" + index + " value:" + value);
Node newNode = new Node(value);//由value创建一个新节点newNode
Node node = array[index];//由index得到一个节点node
if (node == null) {//若这个由index得到的节点是空,则将新节点放入其中
array[index]=newNode;
size++;
} else {//若不为空则遍历这个点上的链表(下一个节点要等于空或者该节点不等于新节点的值--不允许重复)
Node nextNode;
while (!node.getValue().equals(value) && (nextNode = node.getNext())!=null) {
node = nextNode;
}
if (!node.getValue().equals(value)) {//若值不相等则加入新节点
node.setNext(newNode);
size++;
}
}
}
public boolean contains(Object value){
int index = indexFor(hash(value));
Node node = array[index];
while (node!=null && !node.getValue().equals(value)) {
node = node.getNext();
}//横向查找
if (node!=null && node.getValue().equals(value)) {
return true;
} else {
return false;
}
}
public boolean remove(Object value) {
int index = indexFor(hash(value));
Node node = array[index];
if (node!=null && node.getValue().equals(value)) {//若是第一个节点就是要remove的
array[index]=node.getNext();
size--;
return true;
}
Node lastNode = null;
while (node!=null && !node.getValue().equals(value)) {//若不是第一个节点就横向查找
lastNode = node;//记录上一个节点
node = node.getNext();
}
if (node!=null && node.getValue().equals(value)) {
lastNode.setNext(node.getNext());
size--;
return true;
}else {
return false;
}
}
public Object[] getAll() {
Object [] values = new Object[size];
int index = 0;
for (int i = 0; i < array.length; i++) {
Node node = array[i];
while (node!=null) {
values[index++]=node.getValue();
node = node.getNext();
}
}
return values;
}
public static void main(String[] args) {
MyHashSet set = new MyHashSet(6);
Object [] values = {"Tom","Mike","Mike","Jack","Mary","Linda","Rose","Jone"};
for (int i = 0; i < values.length; i++) {
set.add(values[i]);
}
set.remove("Mary");
System.out.println("size="+set.size());
values = set.getAll();
for (int i = 0; i < values.length; i++) {
System.out.println(values[i]);
}
System.out.println(set.contains("Jack"));
System.out.println(set.contains("Linda"));
System.out.println(set.contains("Jane"));
}
}

附:Java中的Hash结构有HashSet和HashMap,哈希表中的每个位置称为桶(bucket),当发生哈希冲突时就以链表形式存放多个元素。

这两个数据结构中有如下属性:

容量:桶的数量,例子中是6.

初始容量:创建时桶的个数。

大小:元素的数目。

负载因子(Load factor):size/capacity,小的冲突少,这两个类可以指定负载因子。当哈希表的负载达到用户设定的负载因子时会自动成倍增加容量,并且重新分配元素位置。默认为0.75,兼顾时间和空间开销。

### Java 实现哈希数据结构Java中,可以通过自定义类来实现基于链的哈希。这种哈希利用数组加链的方式处理冲突问题,在发生碰撞时将元素链接到同一个桶中的不同节点上。 #### 定义哈希类 下面是一个简单的哈希示例,该哈希支持基本操作如插入、删除和查找: ```java import java.util.LinkedList; public class SimpleHashMap<K, V> { private static final int DEFAULT_CAPACITY = 16; private LinkedList<Entry<K,V>>[] buckets; @SuppressWarnings("unchecked") public SimpleHashMap() { this.buckets = (LinkedList<Entry<K,V>>[]) new LinkedList[DEFAULT_CAPACITY]; for(int i=0;i<buckets.length;i++){ buckets[i]=new LinkedList<>(); } } // Hash function to determine bucket index. private int hash(K key){ return Math.abs(key.hashCode()) % buckets.length; } // Entry inner class represents a node in the linked list. private static class Entry<K,V>{ K key; V value; Entry(K k, V v){key=k;value=v;} } // Put method inserts or updates an entry into the map. public void put(K key, V value) { int idx = hash(key); LinkedList<Entry<K,V>> bucket = buckets[idx]; for(Entry<K,V> e : bucket){ if(e.key.equals(key)){ e.value=value; // Update existing value return; } } bucket.add(new Entry<>(key,value)); // Add new entry } // Get method retrieves the value associated with a given key. public V get(Object key) { int idx = hash((K)key); for(Entry<K,V> e:buckets[idx]){ if(e.key.equals(key)) return e.value; } return null; } // Remove method deletes an entry from the map by its key. public boolean remove(Object key) { int idx = hash((K)key); Iterator<Entry<K,V>> it=buckets[idx].iterator(); while(it.hasNext()){ Entry<K,V> e=it.next(); if(e.key.equals(key)){ it.remove(); return true; } } return false; } } ``` 此代码展示了如何创建一个简易版的`SimpleHashMap`[^1]。通过上述方式可以有效地管理键值对,并且能够很好地解决哈希冲突的问题。 对于更复杂的应用场景,建议使用标准库提供的`HashMap`类,其内部已经优化了很多细节并提供了丰富的API接口[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值