When a solution scans the list again for every item, it does O(n^2) work. A hash structure removes the inner scan: a set answers "have I seen this value?" in constant time on average, and a map answers "how many times?" or "where?".
Say what the stored state means before you write the loop. For a pair count, the map holds only the items before the current one, so look up first and store second. Get that order wrong and an item pairs with itself.
A map key can also be something you compute. Sorting a word's letters gives the same key for every rearrangement, which groups them in one pass.
The cost is memory: O(n) extra space for what you store. Test the cases that break hash solutions: an empty list, one item, repeats, negative numbers, and in Java, totals that outgrow an int.
prices = [12, 8, 15, 8, 5], target = 20
price 12: complement 8 seen 0 times pairs = 0 counts {12: 1}
price 8: complement 12 seen 1 time pairs = 1 counts {12: 1, 8: 1}
price 15: complement 5 seen 0 times pairs = 1 counts {.., 15: 1}
price 8: complement 12 seen 1 time pairs = 2 counts {.., 8: 2}
price 5: complement 15 seen 1 time pairs = 3
answer: 3 pairs, in one pass
Look up the complement before storing the current price, so each pair is counted once and no book pairs with itself.