I need to maintain an ordered collection of inputs that disallows duplicates.
The obvious option is LinkedHashSet, but a less obvious option might be a combination of HashSet and List. Here's an example showing both implementations:
class TestClass{
private final Set<ThingIds> setOfThingIds;
private final List<Thing> listOfThings;
private final Set<Thing> linkedHashSetOfThings;
// ... constructor instantiates empty objects
void addThingsViaList(List<Thing> things){
for(var thing: things){
var id = getThingId(thing);
if(setOfThingIds.contains(id)) continue;
setOfThingIds.add(id);
listOfThings.add(thing);
}
}
void addThingsViaSet(List<Thing> things){
for(var thing: things){
linkedHashSetOfThings.add(thing); // thingId calc added to Thing's equals method
}
}
}
When would the first method be useful/required over the second?
One reason I could think of is if there were some bespoke expensive logic to be used for ids so adding it here would localise it and reduce the performance impact (as opposed to adding it on the equals() method where it would be used everywhere...though this is a weak argument since it could be stored on Thing as a field and invoked lazily from equals())...are there any other? Especially ones that aren't micro-optimisations?
equalsandhashCodemethods only look atthingIdand nothing else? These two methods will be used for everything, not just for the LinkedHashSet.containsthenadd, just use return code of add for deciding whether to add to the list.LinkedHashMapwith the id as key and Thing as value.LinkedHashSetas aSequencedSetsince Java 21 seems appropriate here and useful for accessing in order. Or usingSequencedMapimplemented asLinkedHashMap.