<commit_before>package datastructures.hashtable;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Question 7.12: Design and Implement a hash table which uses chaining (linked
 * lists) to handle collisions.
 * 
 * @author <NAME>
 */
public class HashTable<K, V> {
  private HashTableNode<K, V>[] hashArray;
  private int hashSize = 32;
  private int size = 0;
  private Set<HashTableNode<K, V>> entrySet;
  private Set<K> keySet;

  @SuppressWarnings("unchecked")
  public HashTable() {
    hashArray = (HashTableNode<K, V>[]) Arrays.copyOf(new Object[hashSize], hashSize, HashTableNode[].class);
    entrySet = new HashSet<HashTableNode<K, V>>();
    keySet = new HashSet<K>();
  }

  public void put(K key, V value) {
    int index = hash(key);
    HashTableNode<K, V> head = hashArray[index];
    hashArray[index] = add(head, key, value);
  }

  public V get(K key) {
    int index = hash(key);
    HashTableNode<K, V> node = find(hashArray[index], key);
    return (node != null) ? node.value : null;
  }

  public void remove(K key) {
    int index = hash(key);
    HashTableNode<K, V> node = hashArray[index];
    if (node == null) {
      return;
    } else if (node.key.equals(key)) {
      hashArray[index] = node.next;
      entrySet.remove(node);
      keySet.remove(node.key);
      size--;
    } else {
      delete(node, key);
    }
  }

  public boolean containsKey(K key) {
    int index = hash(key);
    if(hashArray[index] == null) {
      return false;
    } else {
      return find(hashArray[index], key) != null;
    }
  }
  
  public int size() {
    return this.size;
  }
  
  public Set<HashTableNode<K, V>> entrySet() {
    return this.entrySet;
  }
  
  public Set<K> keySet() {
    return this.keySet;
  }
  
  private void delete(HashTableNode<K, V> head, K key) {
    HashTableNode<K, V> current = head;
    HashTableNode<K, V> runner = head.next;

    while (runner != null) {
      if (runner.key.equals(key)) {
        current.next = runner.next;
        entrySet.remove(runner);
        keySet.remove(runner.key);
        size--;
      }
      current = current.next;
      runner = runner.next;
    }
  }

  private HashTableNode<K, V> add(HashTableNode<K, V> head, K key, V value) {
    HashTableNode<K, V> node = find(head, key);
    if (node != null) {
      node.value = value;
    } else {
      node = new HashTableNode<K, V>(key, value);
      node.next = head;
      head = node;
      entrySet.add(node);
      keySet.add(key);
      size++;
    }
    return head;
  }

  private HashTableNode<K, V> find(HashTableNode<K, V> head, K key) {
    HashTableNode<K, V> current = head;
    while (current != null) {
      if (current.key.equals(key)) {
        return current;
      }
      current = current.next;
    }
    return null;
  }

  private int hash(K key) {
    return (key.hashCode() % hashSize);
  }
}<commit_msg>Expand HashTable when LoadFactor increases THRESHOLD<commit_after>package datastructures.hashtable;

import java.util.HashSet;
import java.util.Set;

/**
 * Question 7.12: Design and Implement a hash table which uses chaining (linked
 * lists) to handle collisions.
 * 
 * @author <NAME>
 */
public class HashTable<K, V> {
  private HashTableNode<K, V>[] hashArray;
  private final int INITIAL_CAPACITY = 32;
  private final double THRESHOLD = 0.75;
  
  private int currentCapacity = INITIAL_CAPACITY;
  private int size = 0;
  private Set<HashTableNode<K, V>> entrySet;
  private Set<K> keySet;

  @SuppressWarnings("unchecked")
  public HashTable() {
    hashArray = new HashTableNode[INITIAL_CAPACITY];
    entrySet = new HashSet<HashTableNode<K, V>>();
    keySet = new HashSet<K>();
  }

  public void put(K key, V value) {
    int index = hash(key);
    HashTableNode<K, V> head = hashArray[index];
    hashArray[index] = add(head, key, value);
    
    if(loadFactor() > THRESHOLD) {
      expand();
    }
  }

  public V get(K key) {
    int index = hash(key);
    HashTableNode<K, V> node = find(hashArray[index], key);
    return (node != null) ? node.value : null;
  }

  public void remove(K key) {
    int index = hash(key);
    HashTableNode<K, V> node = hashArray[index];
    if (node == null) {
      return;
    } else if (node.key.equals(key)) {
      hashArray[index] = node.next;
      entrySet.remove(node);
      keySet.remove(node.key);
      size--;
    } else {
      delete(node, key);
    }
  }

  public boolean containsKey(K key) {
    int index = hash(key);
    if(hashArray[index] == null) {
      return false;
    } else {
      return find(hashArray[index], key) != null;
    }
  }
  
  public int size() {
    return this.size;
  }
  
  public Set<HashTableNode<K, V>> entrySet() {
    return this.entrySet;
  }
  
  public Set<K> keySet() {
    return this.keySet;
  }
  
  private void delete(HashTableNode<K, V> head, K key) {
    HashTableNode<K, V> current = head;
    HashTableNode<K, V> runner = head.next;

    while (runner != null) {
      if (runner.key.equals(key)) {
        current.next = runner.next;
        entrySet.remove(runner);
        keySet.remove(runner.key);
        size--;
      }
      current = current.next;
      runner = runner.next;
    }
  }

  private HashTableNode<K, V> add(HashTableNode<K, V> head, K key, V value) {
    HashTableNode<K, V> node = find(head, key);
    if (node != null) {
      node.value = value;
    } else {
      node = new HashTableNode<K, V>(key, value);
      node.next = head;
      head = node;
      entrySet.add(node);
      keySet.add(key);
      size++;
    }
    return head;
  }

  private HashTableNode<K, V> find(HashTableNode<K, V> head, K key) {
    HashTableNode<K, V> current = head;
    while (current != null) {
      if (current.key.equals(key)) {
        return current;
      }
      current = current.next;
    }
    return null;
  }

  private int hash(K key) {
    return (key.hashCode() % currentCapacity);
  }
  
  private double loadFactor() {
    return (size/currentCapacity);
  }
  
  @SuppressWarnings({ "rawtypes", "unchecked" })
  private void expand() {
    currentCapacity = (currentCapacity * 2);
    HashTableNode[] newArray = new HashTableNode[currentCapacity];
    System.arraycopy(hashArray, 0, newArray, 0, size);
    hashArray = newArray;
  }
}
{'fraction_non_alphanumeric': 0.13692087247253623, 'fraction_numerical': 0.0028657857029135486, 'mean_word_length': 2.7061946902654865, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2401147', 'n_tokens_mistral': 2177, 'n_tokens_neox': 2144, 'n_words': 541}