I have to implement a hash table which will use an array, however have to follow a guide and create functions for each procedure.
I would appreciate if anyone could help out in completing this for me as I am having some trouble.
public class HashTable {
// public for testing purposes
public int buckets[];
public HashTable(long _a, long _c, long _m) {
}
public void insert(int key) {
}
}
What I've got so far:
public class HashTable {
// public for testing purposes
public int buckets[];
public HashTable(long _a, long _c, long _m) {
table = new Node[];
}
public void insert(int key) {
Node<T> newNode = new Node(key);
int posPosition = calPosition(key);
}
I have included what I have done so far. Maybe I'm going about it the wrong way. I understand the concept but cannot seem to write code for the hash table so far. Would appreciate any help, Thanks Again
A hash table is simply a list or array of buckets.
Each bucket holds all items the key that hashes to for that particular bucket.
those items are entries that contain the key and the value you are seeking.
When putting something in a hash table, you use the key/value pair. If the buckets are in an array, use the hash code of the key to get the proper index of the array. If you use a linked list you might have to count to the location.
Then use another array or linked list to store then entry at that cell. Linked lists are better, imo, because they can be added without worry of exceeding the size of the array. They can just be added to the front like a regular linked list.
When adding a value, create the entry, hash the key and find the bucket. Then add the entry to the bucket.
When retrieving a value, hash the key, get to the bucket and do a linear search on the bucket to find the entry for the key you are looking for. Then return the value for that entry.
Note: As with most hash tables, you cannot have duplicate keys. And any Object which is used as a key must override equals and hashCode for this to work.
Related
I am supposed to make a chain hash table to put names in each bucket as a linked list. I know how to do this with buckets that hold one value but I do not know how to put a link list in each bucket. I have a person class with first and last name already as well as a hashcode class. I have written remove but I am not sure how to put a LinkedList into the method. I also have a bucketList class; is this where I need to implement the LinkedList? If I can get some pointers on what do on the remove or put methods, I should be able to figure out how to do the rest. Thank you
public class MyChainHashTable<K, V> {
private static final int BUCKET_COUNT = 10;
private BucketList[] buckets = new BucketList[BUCKET_COUNT];
private void remove(K key, V value) {
int bucketIndex = key.hashCode(); //TODO
int bucketsProbed = 0;
while (!buckets[bucketIndex].isEmptySinceStart() && bucketsProbed < BUCKET_COUNT) {
// if this bucket isn't empty, and it matches what we're looking for
if (!buckets[bucketIndex].isEmpty()
&& buckets[bucketIndex].getElement().equals(value)) {
buckets[bucketIndex].clear();
return;
}
bucketsProbed++;
bucketIndex++;
bucketIndex %= BUCKET_COUNT; // circle back to 0
}
}
private boolean put(K key, V value) {
return false;
}
private void showTable() {
// old phone UI
String[] keyBoard = {"1 ", "2 ABC", "3 DEF", "4 GHI", "5 JKL",
"6 MNO", "7 PRS", "8 TUV", "9 WXY", "0 "};
}
So from what I gather you want to implement a hash table with linked lists. I also saw this comment
BucketList generically – Rawsick
So let me try and implement parts of this data structure.
Let's start with BucketList. Since this sounds like a just a Bucket with a generic parameter T defining the bucket and V which is what's in the bucket. I'm gonna refactor it to Bucket<T, V>
public class Bucket<T extends Colletion<V>, V> {
private T bucket;
public T add(V value) {
return bucket.add(V);
}
// More functions here
}
Now the hash table,
public class MyChainHashTable<K, V> {
private static final int BUCKET_COUNT = 10;
// Advisable to use a resizeable array here, like an ArrayList
// No need for bucket count then
private Bucket<LinkedList, V>[] buckets = new Bucket<>[BUCKET_COUNT];
public V put(K key, V value) {
int bucketIndex = key.hashCode() % BUCKET_COUNT;
buckets[bucketIndex].add(V);
}
// More functions here
}
This was a very simple approach to a hash table, only the bucket itself was slightly complicated in that the bucket could store values in the form of any class from the Java Collections framework.
I would advise reading into the source code of several popular implementations of collections in Java. You will get a better idea of how to approach problems like this.
Check out google's Gauva library. Look at some of the complex collections like MultiMap and go through how they implemented it.
I think a Chained HashTable is really a HashTable of HashTables which maps your hash key to a HashTable so that you don't have to jump around the table when you have key collisions.
Your asking for a variant of that with a HashTable of LinkedLists instead of a HashTable of HashTables.
In a basic HashTable you need to compute the next index to try when you get a key collision, basically what your doing with bucketIndex %= BUCKET_COUNT; but with a chained HashTable you don't do that. Instead of inserting your element at the indexed location in your underlying array, your array is an array of HashTables (or an array of LinkedLists in your case) and you insert your elements into that collection.
I have a hash map which uses linear probing to deal with collisions. I would like to traverse it. Conceptually, this is quite easy, however, the use of generics is spinning me off.
The entries in the internal array of the hash map have their key-value pairs as generics - like this
public entry(K key, V value) {
this.key = key;
this.value = value;
}
These entries are stored in an entry array - like this
private entry[] entries;
I would like to traverse the hash map beginning at a certain key, I will reach the end of the internal array, then go back to the beginning of the array up to the key, in a circular fashion so the whole array is covered.
public V traverse(K k) {
//look from current key
for(int i = (int)k; i < entries.length; i++){
//visit node
}
//go back to start, and look up to key
for(int i = 0; i < (int)k; i++){
//visit node
}
}
I've realized that type casting the key as an integer was sort of stupid, but i'm struggling to find a working way to actually do this traversal.
If I understood you maybe you can create LinkedHashMap(HashMap)() and with it you can do it transversally.
A HashMap does not store the entries in the order you expect. The ordering is based on the hash of the key, and organized as an array of linked-lists.
If you want to have a defined ordering you should use TreeMap, which uses the natural ordering of the key. If you need a custom sorting you can provide a Comparator by constructor. Then just iterate on the map.keySet.
But I think what you need (starting the iteration somewhere in the middle) is not supported. You start iterating at the first node, and do nothing until you reach your desired key, then do your work with the rest of the entries, then start again iterating until you reach your desired key again.
This question already has answers here:
HashMap with multiple values under the same key
(21 answers)
Closed 6 years ago.
I have 100 entries and I have to have to hash these into a hashtable of a limited size.
I know how to work with the first entry, ht.put(k,v) does the trick.
But as soon as I want to add another value to it, the old one gets overwritten. I don't want to do that, I want to append it in a linkedlist or arraylist.
Hashtable<Integer,Integer> ht = new Hashtable<Integer,Integer>(211);
ht.put(1, 40);
ht.put (1, 60);
System.out.println(ht.get(1));
// output is 60
How to make it both 40 and 60?
You can have List as value type like:
Hashtable<Integer,List<Integer>> ht = new Hashtable<Integer,List<Integer>>(211);
And your put operation would look like:
public static void put(Hashtable<Integer,List<Integer>> ht, int key, int value) {
List<Integer> list = ht.get(key);
if (list == null) {
list = new ArrayList<Integer>();
ht.put(key, list);
}
list.add(value);
}
[UPDATE1]
If you want you can make your one extension of Hashtable like:
public class MyHashtable extends Hashtable<Integer,List<Integer>> {
public MyHashtable(...) { // add params if needed
super(...);
}
// with additional method:
public static void putOne(int key, int value) {
List<Integer> list = this.get(key);
if (list == null) {
list = new ArrayList<Integer>();
this.put(key, list);
}
list.add(value);
}
}
You need linear probing http://www.sanfoundry.com/java-program-implement-hash-tables-linear-probing/
It's not possible to store more than one value in a cell of a hash table
When trying to map a new key to an already occupied cell this is called a collision.
There are a few algorithm schemes to try and work around collision, one is Linear probing - which finds the next most appropriate free space for the key to be stored
The data structure you are looking for is called Multi Map. By definition it has different interface than a map, because it allows multiple values associated with the same key.
There's no standard library implementation for this data structure yet. But you can find good ones in some open source libraries:
Guava
Apache Commons Collections
Multimap (https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/Multimap.html) should help if you are allowed to use it.
Alternatively, you could use Map<Integer, List<Integer>>.
You are using same key (1), which is not what you wanted, unless you wanted to add more values to the same key, in that case have hashtable of list of arrays HashMap<Integer,List<Integer>> integerArrayMap.
In Hashtable, the Key MUST be unique, as you are NOT using unique keys, the same value is being replaced. so try to put the values with different keys.
ht.put(1, 40);
ht.put (2, 60);
I suggest you to refer the Hashtable api here:
https://docs.oracle.com/javase/7/docs/api/java/util/Hashtable.html
This question was asked to me in a job interview and I still don't know answer so ask here. Lets say hashCode() of key object returns a fixed integer so HashMap would look like a LinkedList.
How would a duplicate element be found and replaced by new value in map?
e.g. if following 1001 puts are performed in order listed below,
put(1000,1000), put(1,1), put( 2, 2), put ( 3,3 ) ....put(999,999), put(1000,1000 )
Would map be traversed all the way to end and then new one be inserted at head when last put(1000,1000) is performed?
OR
Map has some other way to locate and replace duplicate keys?
First case is correct.
In your case when hashCode() is returning same hash value for all the keys. In the java HashMap, Key and Value both are stored in the bucket as Map.Entry object. When perform the second or further put() operations into the map, it will traverse all the element to check whether Key is already present in the Map. If Key is not found then new Key and Value pair will be added into the linked list. If Key is found in the list then it update the Value for the pair.
Details explanation about java HashMap working: How HashMap works in Java
Take this sample code and run in the debug mode and observe how the new Key and Value pair are inserted into the Map.
In the class you will need to hashCode() (we want to control how the hash codes are generated for Node), toString() (just to output the Node value in SOUT) and equals() (defines the equality of the keys based on the value of Node member variable Integer, for updating the values.) methods for getting it working.
public class HashMapTest {
static class Node {
Integer n;
public Node(int n) {
this.n = n;
}
#Override
public int hashCode() {
return n%3;
}
#Override
public boolean equals(Object object) {
Node node = (Node)object;
return this.n.equals(node.n);
}
#Override
public String toString() {
return n.toString();
}
}
public static void main(String[] args) {
Map<Node, String> map = new HashMap<>();
for (int i = 0; i<6; i++) {
map.put(new Node(i), ""+i); // <-- Debug Point
}
map.put(new Node(0), "xxx");
} // <-- Debug Point
}
First 3 entries in the map: (hash code is n%3)
Three more values: (hash code is n%3)
Now don't confused about the ordering of the node, I have executed them on java 1.8 and HashMap uses TreeNode, an implementation of Red-Black tree as per the code documentation. This can be different in different versions of the java.
Now lets update the Value of Key 0:
When the hash code is the same, the hash map compares objects using the equals method.
For example, let's say you put a bunch of elements in the hash map:
put(1000,1000), put(1,1), put( 2, 2), put ( 3,3 ) ....put(999,999)
And then you do this:
put(1000,1000 )
1000 is already in the map, the hash code is the same, it is also the same in terms of the equals method, so the element will be replaced, no need to iterate further.
Now if you do:
put(1234, 1234)
1234 is not yet in the map. All the elements are in a linked list, due to the fixed hash code. The hash map will iterate over the elements, comparing them using equals. It will be false for all elements, the end of the list will be reached, and the entry will be appended.
JDK implementations changes over time !
In JDK8, if the hashCode() is a constant value, the implementation creates a tree not a linked list in order to protect against DDOS attack 1.
I am trying to create a linked list that will take a large amount of data, either integers or strings, and get the frequency that they occur. I know how to create a basic linked list that would achieve this but since the amount of data is so large, I want to find a quicker way to sort through the data, instead of going through the entire linked list every time I call a certain method. In order to do this I need to make a Pair of <Object, Integer> where the Object is the data and the integer is the frequency it occurs.
So far I have tried creating arrays and lists that would help me sort out the data but cannot figure out how to get it into a Pair that represents the data and frequency. If you have any ideas that can help me at least get started that would be much appreciated.
First of all you must define your own data type, let's say
public FrequencyCount<T> implements Comparable<FrequencyCount<T>>
{
public final T data;
public int frequency;
public int compareTo(FrequencyCount<T> other) {
// implement this method to choose your correct natural ordering
}
}
With a similar object everything becomes trivial:
List<FrequencyCount<Some>> data = new ArrayList<FrequencyCount<Some>>();
Collections.sort(data);
Set<FrequencyCount<Some>> sortedData = new TreeSet<FrequencyCount<Some>>(data);
You could place all values into a List, create a Set from it and then iterate over the Set to find the frequency in the List using Collections.frequency: http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#frequency(java.util.Collection,%20java.lang.Object)
List<Integer> allValues = ...;
Set<Integer> uniqueValues = new HashSet<Integer>(allValues);
for(Integer val : uniqueValues) {
int frequency = Collections.frequency(allValues, val);
// use val and frequency as key and value as you wish
}