HashSet是一种数据结构为基本操做(add, remove, contains and size)提供恒定的时间性能,假设哈希函数在桶之间正确地分散元素。有许多方法能够实现这种数据结构。这篇文章主要使用链表+数组在Java中简单实现hashmap。java
1.定义一个表示链表节点的类node
class Node<T> {
T data;
Node next;
Node(T data) {
this.data = data;
this.next = null;
}
@Override
public String toString() {
return "(" + this.data + ")";
}
}复制代码
2.插入元素数组
插入元素,键和值将执行如下操做:数据结构
插入实现计算size():app
public class MyHashSet<T> {
private static final Integer INITIAL_CAPACITY = 1 << 4; // 16
private Node<T>[] buckets;
private int size;
public MyHashSet(final int capacity) {
this.buckets = new Node[capacity];
this.size = 0;
}
public MyHashSet() {
this(INITIAL_CAPACITY);
}
public void add(T t) {
int index = hashCode(t) % buckets.length;
Node bucket = buckets[index];
Node<T> newNode = new Node<>(t);
if (bucket == null) {
buckets[index] = newNode;
size++;
return;
}
while (bucket.next != null) {
if (bucket.data.equals(t)) {
return;
}
bucket = bucket.next;
}
// 仅在最后一个元素没有添加值时才添加
if (!bucket.data.equals(t)) {
bucket.next = newNode;
size++;
}
}
public int size() {
return size;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("[");
for (Node node: buckets) {
while (node != null) {
sb.append(node);
node = node.next;
}
}
sb.append("]");
return sb.toString();
}
private int hashCode(T t) {
return t == null ? 0 : t.hashCode();
}
}复制代码
3.删除元素ide
使用如下步骤从hashSet中删除元素:函数
public T remove(T t) {
int index = hashCode(t) % buckets.length;
Node bucket = buckets[index];
if (bucket == null) {
throw new NoSuchElementException("No Element Found"); //匹配不上
}
if (bucket.data.equals(t)) {
buckets[index] = bucket.next;
size--;
return t;
}
Node prev = bucket;
while (bucket != null) {
if (bucket.data.equals(t)) {
prev.next = bucket.next;
size--;
return t;
}
prev = bucket;
bucket = bucket.next;
}
return null;
}复制代码
4.测试性能
@Test
public void testMyHashSet() {
MyHashSet<Integer> set = new MyHashSet<>();
set.add(3);
set.add(4);
set.add(8);
set.add(4);
set.add(8);
set.add(1000);
assertEquals(4, set.size());
assertEquals(Integer.valueOf(8), set.remove(8));
assertEquals(3, set.size());
}
@Test
public void testMyHashSet1() {
MyHashSet<String> set = new MyHashSet<>();
set.add("USA");
set.add("Nepal");
set.add("England");
set.add("Netherland");
set.add("Canada");
set.add("Bhutan");
assertEquals(6, set.size());
// test removal of element
assertEquals("Bhutan", set.remove("Bhutan"));
assertEquals(5, set.size());
}复制代码
5.总结测试
1. 时间复杂ui
将不一样的Keys映射到同一索引可能会发生冲突。若是冲突的数量很是高,最坏状况的运行时间为O(N),其中N是Keys的数量。可是咱们一般假设一个良好的实现,将冲突保持在最小,查找时间为O(1)。
2.以上就是关于如何使用基于数组的链表实现hashSet.