Mikkel you lost me with the time complexity thing, must be reading more books?
Time complexity is a measure of how much time (relative) an algorythm takes as compared to the size of a problem.
An algorythm with a constant time complexity will take the same ammount of time, regardless how many elements it has to deal with. An example would be accessing an Array by index, or a Hashmap by key.
An algorythm with a linear time complexity will take a linearly increasing ammount of time as the number of elements increase. Thus if it takes 1 second with 4 elements, it'll take 2 seconds with 8 and 3 seconds with 12, and so on. An example is traversing lists and certain (slow) sorting algorithms.
An algorythm with a logarithmic time complexity will also take more ammounts of time for more elements, but will do so in a logarithmic fashion. An example is the classic "Binary Search" or number guessing game, where your next guess is always exactly half of your previous guess. This technique is used for traversing binary trees, and thus binary trees are faster to access than lists (but are slower for insert/update).
The last often used time complexity is exponential time complexity where an algorithm takes exponentially longer for more elements. Thus if 1 element takes 1 second, 2 elements will take 2 seconds and 3 elements 4 seconds and so on. Obviously large problems of exponential time complexity (like the traveling salesmans problem) cannot be solved by throwing all the worlds processing power at it.
I wonder if someone can explain what a hash table is, how it works and what you might use it for?
Sure. A hashtable is clever mathematics using prime numbers. What happens is you make a 'hash' of your object, and use that much in the same way you would index an array. The catch? Your hashtable needs to be at least twice as big as the ammount of data you plan on using, and on top of that, has to have a length of a prime number. This will help you avoid hash collisions (you can do it without all the prime number and double space if you want, but then you won't get a constant time complexity).
Now the trick here is that two different objects with the same data, will still have the same Hash, so the HashTable will be unable to tell the difference between two different concrete objects with the same data (unlike an array or list for instance). This is useful in a lot of situations, for example if you want to have a cache for intermediate storage of objects, or if you want to use a Factory pattern to create objects for you.
Say you're working in a dynamic environment where you don't want to have hundreds of duplicate objects floating around. You want a so-called Factory class to handle creation, and make sure that for every specific object, only one ever exsists at any given time. So you tell the Factory to create an object with certain parameters. The Factory does a look-up in the HashTable to see if such an object already exists, and if it does, it returns the handle of the exsisting object. If not, it creates a new object, puts it in the HashTable, and returns that object. Thus all your creation problems are solved elegantly.