For lists, we use the Collections.sort(List)
method. What if we want to sort a HashSet
?
Use java.util.TreeSet
as the actual object. When you iterate over this collection, the values come back in a well-defined order.
If you use java.util.HashSet
then the order depends on an internal hash function which is almost certainly not lexicographic (based on content).
Based on the answer given by @LazerBanana i will put my own example of a Set sorted by the Id of the Object:
Set<Clazz> yourSet = [...];
yourSet.stream().sorted(new Comparator<Clazz>() {
@Override
public int compare(Clazz o1, Clazz o2) {
return o1.getId().compareTo(o2.getId());
}
}).collect(Collectors.toList()); // Returns the sorted List (using toSet() wont work)
you can do this in the following ways:
Method 1:
Method 2:
Method 2 is more preferable because the other method consumes lot of time to transfer data back and forth between hashset and list.
If you want want the end Collection
to be in the form of Set
and if you want to define your own natural order
rather than that of TreeSet
then -
1. Convert the HashSet
into List
2. Custom sort the List
using Comparator
3. Convert back the List
into LinkedHashSet
to maintain order
4. Display the LinkedHashSet
Sample program -
package demo31;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
public class App26 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
addElements(set);
List<String> list = new LinkedList<>();
list = convertToList(set);
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
int flag = s2.length() - s1.length();
if(flag != 0) {
return flag;
} else {
return -s1.compareTo(s2);
}
}
});
Set<String> set2 = new LinkedHashSet<>();
set2 = convertToSet(list);
displayElements(set2);
}
public static void addElements(Set<String> set) {
set.add("Hippopotamus");
set.add("Rhinocerous");
set.add("Zebra");
set.add("Tiger");
set.add("Giraffe");
set.add("Cheetah");
set.add("Wolf");
set.add("Fox");
set.add("Dog");
set.add("Cat");
}
public static List<String> convertToList(Set<String> set) {
List<String> list = new LinkedList<>();
for(String element: set) {
list.add(element);
}
return list;
}
public static Set<String> convertToSet(List<String> list) {
Set<String> set = new LinkedHashSet<>();
for(String element: list) {
set.add(element);
}
return set;
}
public static void displayElements(Set<String> set) {
System.out.println(set);
}
}
Output -
[Hippopotamus, Rhinocerous, Giraffe, Cheetah, Zebra, Tiger, Wolf, Fox, Dog, Cat]
Here the collection has been sorted as -
First - Descending order of String
length
Second - Descending order of String
alphabetical hierarchy
Java 8 way to sort it would be:
fooHashSet.stream()
.sorted(Comparator.comparing(Foo::getSize)) //comparator - how you want to sort it
.collect(Collectors.toList()); //collector - what you want to collect it to
*Foo::getSize
it's an example how to sort the HashSet of YourItem's naturally by size.
*Collectors.toList()
is going to collect the result of sorting into a List the you will need to capture it with List<Foo> sortedListOfFoo =
In my humble opinion , LazerBanana's answer should be the top rated answer & accepted because all the other answers pointing to java.util.TreeSet
( or first convert to list then call Collections.sort(...)
on the converted list ) didn't bothered to ask OP as what kind of objects your HashSet
has i.e. if those elements have a predefined natural ordering or not & that is not optional question but a mandatory question.
You just can't go in & start putting your HashSet
elements into a TreeSet
if element type doesn't already implement Comparable
interface or if you are not explicitly passing Comparator
to TreeSet
constructor.
From TreeSet
JavaDoc ,
Constructs a new, empty tree set, sorted according to the natural ordering of its elements. All elements inserted into the set must implement the Comparable interface. Furthermore, all such elements must be mutually comparable: e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the set. If the user attempts to add an element to the set that violates this constraint (for example, the user attempts to add a string element to a set whose elements are integers), the add call will throw a ClassCastException.
That is why only all Java8 stream based answers - where you define your comparator on the spot - only make sense because implementing comparable in POJO becomes optional. Programmer defines comparator as and when needed. Trying to collect into TreeSet
without asking this fundamental question is also incorrect ( Ninja's answer). Assuming object types to be String
or Integer
is also incorrect.
Having said that, other concerns like ,
should be the other relevant points too. Just pointing to API shouldn't be only intention.
Since Original set already contains only unique elements & that constraint is also maintained by sorted set so original set needs to be cleared from memory since data is duplicated.