Option 1 is to avoid arrays and use an ArrayList instead. Then you can declare and create the hash table in the following way:
ArrayList<LinkedList<T>> table = new ArrayList<>();```
And then what I have is a method header for some methods, I need to implement, but where do I use ArrayList?
```java
public class HashSet<T> implements Set<T> {
private List<T>[] table;
/**
* Creates a hash table with the given capacity (amount of buckets).
*
* @throws IllegalArgumentException if capacity <= 0.
*/
public HashSet(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"capacity must be a positive, non-zero value! Provided: " + capacity);
}
@SuppressWarnings("unchecked") // for this declaration only
List<T>[] t = new LinkedList[capacity];
table = t;
}
/**
* Adds the given element to the set.
* @return true if the set did not contain the element, otherwise false.
*/
public boolean add(T elem) {
}
#Need help with implementing hashSet
81 messages · Page 1 of 1 (latest)
⌛ This post has been reserved for your question.
Hey @violet salmon! Please use
/closeor theClose Postbutton above when you're finished. Please remember to follow the help guidelines. This post will be automatically closed after 300 minutes of inactivity.
TIP: Narrow down your issue to simple and precise questions to maximize the chance that others will reply in here.
Basically I really need help understanding how to begin
read this
www.javatpoint.com
Hash Table with Introduction, Asymptotic Analysis, Array, Pointer, Structure, Singly Linked List, Doubly Linked List, Graph, Tree, B Tree, B+ Tree, Avl Tree etc.
hashset uses a hashmap internally
I feel like I understand the concept behind it, but it is that I am confused when it comes to the implemenation. I just need help with starting it, as in maybe understand how and why and where I am gonna use arrayList? Isn't it enough with LinkedList?
but like what is the roll of the arrayList here?
a bucket holder
dunno what is the purpose of using arraylist. array is perfect for that, and arraylist doesn't give any advantage
you can hash an object. Do you understand what is hashing?
If you'd rather use arrays, for efficiency-reasons, some more unexpected issues pop up. You can't actually create an array of generic lists in a type-safe fashion in Java. The following, seemingly natural code:
new LinkedList<T>[size];
doesn't work. HashSet.java is a skeleton that shows how you can get around this.```
I have option 2, to use arrays but they recommend I use arrayList and claim it is easier to work with when it comes to generic types.
So basically linkedlist will be inside the arrayList and it takes one index place?
its dynamically resizable out of the hood maybe thats why they say
yes
well
So the field that you see should be an index then right?
"table" variable I mean*
a hashmap uses linked nodes actually, but ye a linkedlist would work too
it uses a Node<K,V>[], which would translate to ArrayList<LinkedList<T>> in your case
Or the actual arrayList?
or LinkedList<T>[]
what type of list should table be?
i would be using an array
I mean like I need to have a LinkedList no matter what to link the objects with hashcode that are congruent. But lets say I pick array as the outside list? Which list should the field "table" be? Now when I think about since they said that I can choose to have an array and an array is not a list. This means that the List "table" has then the roll of a linkedlist right?
LinkedList<T>[]?
Should I declare the array or the arraylist in the field or where should I have it? I am guessin in the field since I am gonna need to access since I will be implementing multiple methods?
yes
anyone that can help?
In the code you provided, the table variable is declared as an array of List<T>. This is not what the suggested option 1 says to do, which is to use an ArrayList<LinkedList<T>>.
To implement this change, you need to change the declaration of the table variable to an ArrayList<LinkedList<T>> and initialize it as an empty ArrayList in the constructor:
private ArrayList<LinkedList<T>> table;
public HashSet(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"capacity must be a positive, non-zero value! Provided: " + capacity);
}
table = new ArrayList<LinkedList<T>>();
for (int i = 0; i < capacity; i++) {
table.add(new LinkedList<T>());
}
}```
Then in the add method, you can use the ArrayList to access and manipulate the linked lists.
thanks but one more thing
yeah
so using hashcode I will generate the integer representation of the object right? I can't add an extra method that is not given. So then how do I do the module what ever this "%" is called to find it's index in the arrayList?
Yes, you can use the hashCode method to generate the integer representation of an object. You can then use the modulo operator (%) to reduce the value of the hash code to an index within the size of the ArrayList.
example:
public boolean add(T elem) {
int hash = elem.hashCode();
int index = hash % table.size();
LinkedList<T> list = table.get(index);
if (!list.contains(elem)) {
list.add(elem);
return true;
}
return false;
}
The index variable holds the position in the ArrayList where the element should be inserted or checked for existence. The list variable holds the reference to the linked list at that position in the ArrayList. By checking if the linked list at the index position contains the element, you can determine if the element already exists in the set. If the element does not exist, you can add it to the linked list.
Keep in mind - when you hash an object, if two objects are considered equal, they should have the same hash.
(As defined in your equals method)
but there are cases when they aren't tho if I remember right?
None that I’m aware of.
If two objects are not equal, they probably do not have the same hash, but they might. If two objects are equal, they must have the same hash.
why did you create a new linkedlist?
I just gave an example
but I rememebr my prof talking about the fact that if they did then I will have to multiplyy with 31 and do some math to it? But I assume hashCode method takes care of that right?
but like wouldn't I need to creat new linked list for every index in the ArrayList?
Multiplying by 31 is just a way to try to get things that are not equal to have different hashes. That’s generally good to avoid collisions
I understand we only care about this index but like in general?
There are other numbers besides 31, idk exactly the best numbers. But that’s generally why people do it
Here’s my introduction to hash tables and dictionaries!
The coding interview problem I mentioned at the end: https://youtu.be/GJdiM-muYqc
And here’s my Python implementation: https://gist.github.com/ykdojo/4f9741398c3653d3dc8b95ef52bb3fcf
Also, some more info about djb2: http://www.cse.yorku.ca/~oz/hash.html
But wait so if it happens that "a" and "b" happens to have the same hashes. Java would say they are equal even tho they aren't right so how can I make sure it doesn't happen? I thought that hashCode method took care of that already?
No. If two objects have the same hash, then java checks them with their equals function.
The same thing happens with different hashes with collisions
I will check that out but he is a python teacher tho? Does it matter if I watch his videos for java? I usually avoid his videos lol
The data structures stuff is mostly for the theory, not the code.
The theory is the same in pretty much every language.
Implementation is just different
Alright I will check that out and thank you guys for the help
I tried implementing my method the way you said to, but the problem I am facing is that you had said to change table to ArrayList but in the HashSet constructor they have already set it to LinkedList. Now I'm confused again?
what option did you choose? What do you have at the moment?
I chose ArrayList
make sure you have sufficient initial capacity, so it won't resize automatically as you will be adding values, and it won't mess up with buckets 😉
oh nevermind, it shouldn't
Ok, but it is type mis match error tho since someone told me to change the field variable type to ArrayList as option 1 suggests/states. But later in the capacity method they set "table = t". These two objects are not the same type since t is an Arraylist and t is an array of type LinkedList?
better show the code
repost it?
you mean the one in the very first message?
there is array of lists
not arraylist of lists
public class HashSet<T> implements Set<T> {
private List<T>[] table;
/**
* Creates a hash table with the given capacity (amount of buckets).
*
* @throws IllegalArgumentException if capacity <= 0.
*/
public HashSet(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"capacity must be a positive, non-zero value! Provided: " + capacity);
}
@SuppressWarnings("unchecked") // for this declaration only
List<T>[] t = new LinkedList[capacity];
table = t;
}
/**
* Adds the given element to the set.
* @return true if the set did not contain the element, otherwise false.
*/
public boolean add(T elem) {
int hashCode = elem.hashCode();
int index = hashCode % table.size();
LinkedList<T> indexList = table.get(index);
if(!indexList.contains(elem)){
indexList.add(elem);
return true;
}
else{
return false;
}```
if you want to use option 2 (as it is in your code - you use array of lists) I would recommend you to cast raw type to List<T> like this:```java
List<T>[] t = (List<T>[])new LinkedList[capacity];
besides, why don't you assign it directly?
table = (List<T>[])new LinkedList[capacity];
I mean I didn't write the code, it is given. I am just supposed to implement methods for the interface. That is why I find it very confusing because it is not really making sense to me? Why can't I use ArrayLists?
instead of array or instead of LinkedList?
Ah, I see what the issue is now. In the HashSet class, the table variable is declared as an array of List objects, but it is initialized as an array of LinkedList objects:
private List<T>[] table;
public HashSet(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"capacity must be a positive, non-zero value! Provided: " + capacity);
}
@SuppressWarnings("unchecked") // for this declaration only
List<T>[] t = new LinkedList[capacity];
table = t;
}```
To use an ArrayList instead of a linked list array, you would need to change the declaration of the table variable and the initialization of t:
```java
private ArrayList<LinkedList<T>> table;
public HashSet(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException(
"capacity must be a positive, non-zero value! Provided: " + capacity);
}
table = new ArrayList<>(capacity);
for (int i = 0; i < capacity; i++) {
table.add(new LinkedList<T>());
}
}```
And in the add method, you would retrieve the linked list at the specified index in the ArrayList as follows:
```java
public boolean add(T elem) {
int hash = elem.hashCode();
int index = hash % table.size();
LinkedList<T> list = table.get(index);
if (!list.contains(elem)) {
list.add(elem);
return true;
}
return false;
}
But if I use an array, do I still need to alter the HashSet method? The thing is I'm not sure if I'm allowed (usually not allowed) to alter anything else except the method header in teh interface. But if there is not other way of doing it(looks like there is no other way since you can't magically make two different type equal), I guess I'd need to alter it.
Also why don't I need @SuppressWarnings("unchecked) anymore?
anyone?
If you're not allowed to change the declaration of the table variable or the constructor of the HashSet class, then you would need to use an array of linked lists instead of an ArrayList.
Here's an implementation of the add method using an array of linked lists:
public boolean add(T elem) {
int hash = elem.hashCode();
int index = hash % table.length;
LinkedList<T> list = table[index];
if (!list.contains(elem)) {
list.add(elem);
return true;
}
return false;
}
This implementation works the same way as the one using an ArrayList, but instead of using the get method to retrieve the linked list at the specified index, it uses the array indexing operator [] to access the linked list at that index in the table array.
The @SuppressWarnings("unchecked") annotation was used in the original implementation to suppress the compiler warning that arises when using an array of a non-reifiable type, such as List<T>[]. In this new implementation, you are using an array of a concrete type, LinkedList<T>[], which is a reifiable type, so there's no need to use the @SuppressWarnings("unchecked") annotation anymore.