This answer summarises parts of TAoCP Vol 3, Ch 6.4.
Assume we have a set of values $V$, $n$ of which we want to store in an array $A$ of size $m$. We employ a hash function $h : V \to [0..M)$; typically, $M \ll |V|$. We call $\alpha = \frac{n}{m}$ the load factor of $A$.
Here, we will assume the natural $m=M$; in practical scenarios, we have $m \ll M$, though, and have to map down to $m$ ourselves.
The first observation is that even if $h$ has uniform characteristics¹ the probability of two values having the same hash value is high; this is essentially an instance of the infamous birthday paradox. Therefore, we will usually have to deal with conflicts and can abandon hope of $\mathcal{O}(1)$ worst case access time.
What about the average case, though? Let us assume that every key from $[0..M)$ occurs with the same probability. The average number of checked entries $C_n^S$ (successful search) resp. $C_n^U$ (unsuccessful search) depends on the conflict resolution method used.
Chaining
Every array entry contains (a pointer to the head of) a linked lists. This is a good idea because the expected list length is small ($\frac{n}{m}$) even though the probability for having collisions is high. In the end, we get
\[ C_n^S \approx 1 + \frac{\alpha}{2} \quad \text{ and } \quad C_n^U \approx 1 + \frac{\alpha^2}{2} .\]
This can be improved slightly by storing the lists (partly or completely) inside the table.
Linear Probing
When inserting (resp. searching a value) $v$, check positions
\[h(v), h(v)-1,\dots,0,m-1,\dots,h(v)+1\]
in this order until an empty position (resp. $v$) is found. The advantage is that we work locally and without secondary data structures; however, the number of average accesses diverges for $\alpha \to 1$:
\[ C_n^S \approx \frac{1}{2}\left(1 +\frac{1}{1-\alpha}\right) \quad \text{ and } \quad C_n^U \approx \frac{1}{2}\left(1 +\left(\frac{1}{1-\alpha}\right)^2\right).\]
For $\alpha < 0.75$, however, performance is comparable to chaining².
Double Hashing
Similar to linear probing but search step size is controlled by a second hash function that is coprime to $M$. No formal derivation is given, but empirical observations suggest
\[ C_n^S \approx \frac{1}{\alpha}\ln\left(\frac{1}{1-\alpha}\right)\quad \text{ and } \quad C_n^U \approx \frac{1}{1-\alpha} .\]
This method has been adapted by Brent; his variant amortises increased insertion costs with cheaper searches.
Note that removing elements from and extending tables has varying degrees of difficulty for the respective methods.
Bottom-line, you have to choose an implementation that adapts well to your typical use cases. Expected access time in $\mathcal{O}(1)$ is possible if not always guaranteed. Depending on the used method, keeping $\alpha$ low is essential; you have to trade off (expected) access time versus space overhead. A good choice for $h$ is also central, obviously.
1] As arbitrarily dumb uninformed programmers may provide $h$, any assumption regarding its quality is a stretch in practice.
2] Note how this coincides with recommendations for usage of Java's Hashtable
.