Lists, sets, and maps each do one job well. Real code moves values between them, and Apex makes that a one line job because each collection can be built straight from another.
Passing a list into a set constructor copies every value in and drops the repeats:
List<String> visits = new List<String>{ 'apex', 'soql', 'apex' };
Set<String> unique = new Set<String>(visits);
System.debug(unique.size()); // 2
A set has no positions and cannot be sorted, so convert it back to a list when you need order:
List<String> uniqueList = new List<String>(unique); uniqueList.sort(); System.debug(uniqueList[0]); // apex
This round trip, list to set to list, is the standard way to get the distinct values of a list in a shape you can sort or index.
A map hands you both of its halves as ready made collections. values() is already a List, and keySet() returns a Set that the list constructor accepts:
Map<String, Integer> stock = new Map<String, Integer>{ 'pens' => 12, 'paper' => 4 };
List<String> itemNames = new List<String>(stock.keySet());
List<Integer> counts = stock.values();
Every one of these conversions copies the values into a new collection. Changing the new one does not change the one you started from, so keep working with the result and not the original.
Each shape unlocks different methods. Sets remove duplicates, lists sort and index, maps look values up by key. Converting between them means you never have to pick one shape and live with its limits.