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.