Java
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Java
-
Section 4: Collections Framework
-
Section 5: Exception Handling
-
Section 6: Generics
-
Section 7: Functional Java
-
Section 8: Concurrency
-
Section 9: I/O and NIO
-
Section 10: JVM Internals
-
Section 11: Modern Java Features
-
Section 12: Build Tools and Project Structure
-
Section 13: Testing
-
Section 14: Databases and Persistence
-
Section 15: Networking
-
Section 16: Design and Best Practices
-
Section 17: Reflection and Annotations
-
Section 18: Logging and Diagnostics
-
Section 19: Date, Time, and Internationalization
-
Section 20: Java Platform Module System
-
Section 21: Security in Java
-
Section 22: Advanced Collections and Data Structures
-
Section 23: More Concurrency Patterns
-
Section 24: Compression, Files, and System Integration
-
Section 25: GUI Programming
-
Section 26: Practical Projects
-
Section 27: Data Structures and Algorithms
-
Section 28: Interview and Algorithm Practice
-
Section 29: JSON and Data Interchange
-
Section 30: More Concurrency Utilities
-
Section 31: More Collections and Streams Practice
-
Section 32: More File and System Programming
-
Section 33: Standard Library Deep Dive
-
Section 34: More Practice and Drills
-
Section 35: More Testing and Quality
-
Section 36: More Design Patterns and Architecture
-
Section 37: Career and Ecosystem
-
Section 38: More OOP and Architecture Practice
-
Section 39: More Enterprise Concepts
-
Section 40: Advanced JavaFX
-
Section 41: More Interview Practice
45: HashSet vs TreeSet vs LinkedHashSet
By now, you know that a Set is your go-to when you need to ensure no duplicates exist in a collection. But when you actually go to instantiate one, you'll notice Java gives you three main flavors. Choosing the wrong one won't usually break your code, but it can definitely tank your performance or make your UI behave unpredictably.
If I just need a set of unique items, which one do I pick?
In the vast majority of your professional work, you'll reach for HashSet. It's the "default" for a reason: it's incredibly fast. It uses a hash table under the hood, meaning adding, removing, and checking if an item exists (the contains() method) happens in constant time—O(1).
The trade-off? It's completely chaotic. It doesn't remember the order you added items, and it certainly doesn't sort them. If you print a HashSet, the order might look random, and it could even change if you add more elements. If you don't care about order, don't pay the performance tax for it.
// Quick and dirty: just make sure the usernames are unique
Set<String> usernames = new HashSet<>();
usernames.add("ShadowSlayer");
usernames.add("PixelKnight");
usernames.add("DragonBorn");
usernames.add("ShadowSlayer"); // Duplicate! This will be ignored.
System.out.println(usernames);
// Output could be: [PixelKnight, DragonBorn, ShadowSlayer] (completely arbitrary)
I need my data to stay in the order I added it; is LinkedHashSet the way to go?
Exactly. I've seen developers try to use a List and then manually check contains() before every add() to prevent duplicates. Please, don't do that. That turns your addition process into O(n) complexity, which is a nightmare as your data grows.
LinkedHashSet is essentially a HashSet with a linked list running through it. It maintains a doubly-linked list of the elements in the order they were inserted. You get the same O(1) performance for basic operations, but when you iterate over the set, you get the items back exactly as they went in.
// Useful for things like "Recent Search Terms" where order matters
Set<String> recentSearches = new LinkedHashSet<>();
recentSearches.add("Java Collections");
recentSearches.add("Spring Boot");
recentSearches.add("Docker Compose");
System.out.println(recentSearches);
// Guaranteed output: [Java Collections, Spring Boot, Docker Compose]
Is TreeSet always better because it keeps everything sorted?
Not at all. In fact, TreeSet is the "slowest" of the three. It uses a Red-Black tree internally, which means operations take O(log n) time. While that's still fast, it's noticeably slower than the O(1) of a HashSet when you're dealing with millions of records.
The biggest "gotcha" with TreeSet is that it requires the elements to be comparable. If you try to put a custom object into a TreeSet without implementing the Comparable interface (or providing a Comparator), your code will throw a ClassCastException at runtime. I've spent way too many hours debugging that specific mistake in my early career.
// Perfect for a high-score board where names must be alphabetical
Set<String> leaderboard = new TreeSet<>();
leaderboard.add("Zelda");
leaderboard.add("Mario");
leaderboard.add("Link");
System.out.println(leaderboard);
// Guaranteed alphabetical: [Link, Mario, Zelda]
📋 Practical Task
Building a Product Tagging System
Imagine you are building a backend for an e-commerce site. You need to implement a TagManager class that handles product tags (like "Sale", "Electronics", "New Arrival").
Implement a class with the following requirements:
- Create a method
addTagInOrder(String tag)that stores tags in the exact order they were added by the administrator. - Create a method
addTagSorted(String tag)that stores tags so they are always retrieved in alphabetical order, regardless of when they were added. - Ensure both methods prevent duplicate tags from being added.
- Create a method
displayTags()that prints both collections to the console to demonstrate the difference in behavior.
Testing your code: Add "Summer", "Accessories", and "Sale" to both sets. Your "In Order" set should print them exactly in that sequence; your "Sorted" set should print "Accessories", "Sale", "Summer".
There are no comments for now.