I'm using a hash table to load/remove/retrieve my resources and as of now what I am doing is I have an array of linked lists. I have a hash function that generates an index to place the resource in and it gets added to the linked list in that index. To retreive a resource I call the hash function again to find the index of the element and then find the resource thats key value corresponds with what was used in the hash function
You are almost literally describing the exact algorithm used by `std::unordered_map`. Just use that and stop worrying about it.
Your conceptual problem is just a fundamental one with hash tables. There are sometimes collisions. Bad hash functions (...like the one you're using) can exasperate those problems and make them far worse.
The only way to avoid collisions in a hash table is to use a perfect hash function. There is no universal perfect hash function. You generally have to find one for a given data set, which is not an operation you can generally perform during runtime of a game. Some games when baking their resources for the game will generate a perfect hash function for that fixed set of resources and then uses that hash function to generate a very efficient index in the game's pack file(s), while other games will just roll the dice and use a high-fidelity hash and hope that there's no collisions (possibly spitting out a content error if there are). Yet other games generate unique fixed-size keys for resources (i.e. UUIDs) and then use those in all their tables and references.
Also, when you're walking a linked list of items, thinking that using an integer key is going to make a huge different is a bit pointless. Yes, comparing integers is more efficient, but if you're already doing something inefficient... comparing small strings in a std::string will be much faster in many cases than following a single linked list pointer (std::string typically employs the small-buffer optimization, so a std::string can contain small strings with no external pointers, so comparing small string keys requires no extra memory accesses while following a linked list pointer is quite likely going to cause a cache miss + memory fetch + pipeline stall.)
Now, if you replaced your mediocre hash table with a more efficient
open-addressing hash table (with a sensible probing strategy) then you will possibly find that comparing keys is one of your bottlenecks. Switching to comparing the hashes while following chains could be a big help. But more likely you'll find that either your probing strategy or your memory layout is a bigger cost (e.g., do you store keys and values interleaved in memory? that'll make probing result in more cache misses...).
Ultimately, though, just profile your code and find out what's slow for sure rather than guessing randomly. If you want decent performance without lots of analysis work then use the STL containers like std::unordered_map instead of writing your own and then only replace them if/when they become a bottleneck.