When you look at this code
List<Person> persons;
what do you think, what do you expect?
I expect a collection of people with possible duplicated elements:
List[
,
,
,
] persons;
but I saw in many projects that developers use List to store unique objects:
List[
,
,
] persons;
Photo Ryan McGuire from Pixabay, Photo by Alvin Balemesa on Unsplash
You may ask: is that really a problem? Yes, it is.
Why using a List to store unique objects is a bad idea?
- Expressing wrong assumptions
From a design perspective, List suggests that this collection can and probably does store the same objects many times and we don’t care about uniqueness. This is a strong assumption. When developers see a List, they put everything into it because they have no idea that you defined a list to store unique objects.
- You won’t protect your list from change
You may think: I define a List and take care of adding unique objects, so my list is safe. No, the code is shared among team members and we currently use a structured/procedural programming style of coding – code in different parts of system/application operates on the same data:
//in one part of the system
persons.add(new Person(adam@wiocha.pl));
//in other part of the system
persons.add(new Person(adam@wiocha.pl));
Then, for example, the payment process use the person list and sent a request for payment
persons.forEach(Payment::sentRequestForPayment)
and …. the user receives the request for payment twice! This is an error. You can easily solve it:
persons.distinct().forEach(Payment::sentRequestForPayment)
No, this is not the best solution, because the list of people can be used in many places, so you have to correct them all, or you can try to find/trace the logic responsible for adding the same person again, which is difficult and time-consuming.
How to solve it?
If you need a collection of unique objects use Set and prevent future problems.
Why using a Set to store unique objects is a good practice?
- Express correct assumptions
When developers in code see Set:
Set<Person> persons;
they assume that collection contains only unique objects (btw to achieve uniquness of objects you have to define, in case of java language, equals() and hashcode methods)
- Set prevents by adding the same object twice*
boolean added = persons.add(new Person("Tom")); //added = true
added = persons.add(new Person("Tom")); //added = false
*(it is java specific) You should (it is good practice) check the returned boolean value of the add() function. If add() returns ‘false’ it could mean something undesirable e.g. uniqueness of objects is different than you assume, so always check the equals() and hashcode() implementation of the objects you are adding.
Summary
Whenever you want to define a collection of objects, start with this question:
Does the collection contain only unique objects?
If so, choose Set. If you are not sure, also start with Set as a more restrictive solution. If you are sure that the collection will contain duplicate objects choose List.