6

Apologies for the newbie question, but what's the proper way to get a Set (say LinkedHashSet) in reverse order? For Collections there's Collections.reverse(Collection c), but how does one do it for a Set with ordered elements (like a LinkedHashSet)?

carlspring
  • 31,231
  • 29
  • 115
  • 197
  • 5
    A `Set` doesn't have an order. Can you clarify? Also, `reverse` takes a `List`. – Sotirios Delimanolis Mar 06 '14 at 00:28
  • 1
    Okay... I mean a `LinkedHashSet` (which is ordered). What's the best way to reverse it? Do I need to get the iterator and just iterate over it, or is there a smarter way? – carlspring Mar 06 '14 at 00:31
  • 3
    @SotiriosDelimanolis In Java, `TreeSet`s keep their items in sorted order. To get at the elements in reverse order, you can use the `descendingSet()` method. For `LinkedHashSet`, see this answer: http://stackoverflow.com/questions/10741902/java-linkedhashset-backwards-iteration – dlev Mar 06 '14 at 00:31
  • 4
    A `LinkedHashSet` is not _ordered_ it is `Linked`. If you want to loop over the items in reverse order of insertion use an `Iterator`. – Boris the Spider Mar 06 '14 at 00:32
  • 2
    @BoristheSpider It's really dependent on what you mean by "ordered". `TreeSet` maintains a "sorted" order, whereas `LinkedHashSet` maintains the insertion order (and thus does have a predictable iteration order.) – dlev Mar 06 '14 at 00:33
  • 1
    @dlev you're right - it's mainly semantics. – Boris the Spider Mar 06 '14 at 00:37

6 Answers6

18

Sets are not ordered in general, so to preserve the sorting, after sorting the set as a list, you would need to use a known iteration order implementation of Set, such as LinkedHashSet

List list = new ArrayList(set);
Collections.sort(list, Collections.reverseOrder());
Set resultSet = new LinkedHashSet(list);

You could also use TreeSet with a comparator, but that is not as fast as the ArrayList method above.

Peter
  • 972
  • 7
  • 13
  • Wouldn't this be inefficient (memory-wise) with larger sets of data (as you'll end up having the same data in memory twice)? My input is a `Set`, not a `List`. – carlspring Mar 06 '14 at 00:41
  • The Java Collections API doesn't seem to allow for a constant space sorting or an arbitrary Set. You may need to limit yourself to the SortedSet API to expect that from what I can tell. – Peter Apr 02 '14 at 00:44
2
public class LargestArray {
public static void main(String[] args) {

    ArrayList<Integer> al = new ArrayList<>();
    Set<Integer> set = new TreeSet<>();
    set.add(10);
    set.add(20);
    set.add(7);
    set.add(4);
    set.add(1);
    set.add(2);
    set.add(3);
    set.add(4);
    System.out.println("after Sorting");
    for(int i : set) {
        System.out.print("  " + i);
    }
    al.addAll(set);
    set.clear();
    Collections.reverse(al);
    System.out.println();
    System.out.println("After Reverse");
    for (int i : al) {
        System.out.print(" " + i);
    }

}

}

output = after Sorting 1 2 3 4 7 10 20 After Reverse 20 10 7 4 3 2 1

Onic Team
  • 1,620
  • 5
  • 26
  • 37
0

Check this out

http://docs.oracle.com/javase/7/docs/api/java/util/TreeSet.html#descendingSet()

If you use a TreeSet you can get reverse order by calling descendingSet.

Daniel Williams
  • 8,673
  • 4
  • 36
  • 47
  • Wouldn't the `TreeSet` re-order them after I have added them (and mix up the order)...? – carlspring Mar 06 '14 at 00:38
  • No that is why requires a comparator to maintain the order. If the comparator isn't correctly implemented then yes your order can be very strange. – Daniel Williams Mar 06 '14 at 00:42
  • 1
    The OP is using a `LinkedHashSet` - this maintains insertion order. Putting the items into a `TreeSet` would obviously break this. Unless you supplied an explicit ordering comparator - which defeats the object somewhat. – Boris the Spider Mar 06 '14 at 01:01
  • 1
    Ah that was added in an edit. I'm surprised LinkedHashSet doesn't have a reverse iterator since the docs say the implementation is backed by a doubly linked list. – Daniel Williams Mar 06 '14 at 01:07
  • That was indeed added a minute, or two after I added the post. Sorry about that. – carlspring Mar 06 '14 at 01:09
0

I will explain you with an example. Comments are added in mid of the code for better understanding.

public class ReverseLinkedHashSet {

    public static void main(String[] args) {

        // creating a LinkedHashSet object which is
        // of type String or any. Will take a example of String.
        HashSet<String> cars = new LinkedHashSet<String>();

        // adding car elements to LinkedHashSet object as below
        cars.add("Toyato");
        cars.add("Hundai");
        cars.add("Porshe");
        cars.add("BMW");

        // Iterating using enhanced for-loop to see the order.
        System.out.println("Insertion Order: Iterating LinkedHashSet\n");
        for(String car : cars) {
            System.out.println(car);

        // Output will be as below  
        //Toyato
        //Hundai
        //Porshe
        //BMW
        }

        // Now convert to ArrayList to rearrange to reverse
        // the linkedHashset
        List<String> listOfCars = new ArrayList<String>(cars);

        // to reverse LinkedHashSet contents
        Collections.reverse(listOfCars);

        // reverse order of LinkedHashSet contents
        // can be done as below
        System.out.println("\n\n\nReverse Order of LinkedHashSet\n");
        for(String car : listOfCars) {
            System.out.println(car);

        // Output will be as below  
        //BMW
        //Porshe
        //Hundai
        //Toyato    
        }
    }
}

Also, I suggest not to use LinkedhashSet without a strong reason. For a complex application, it will reduce the performance. Use HashSet instead.

carlspring
  • 31,231
  • 29
  • 115
  • 197
Manjunatha B
  • 276
  • 3
  • 9
0

Java 8, I using solution below,

Set<String> setTest = new HashSet<>();

setTest.add("1");
setTest.add("2");
setTest.add("3");

List<String> list = new ArrayList<>(setTest);
list.sort(Collections.reverseOrder());
Set<String> result = new LinkedHashSet<>(list);

for (String item: result) {
    System.out.println("---> " + item);
}

Result:

---> 3
---> 2
---> 1

Work for me.

bamossza
  • 3,676
  • 1
  • 29
  • 28
0

Java 21 is introducing the SequencedSet interface for reversible sets which have a well defined insertion order. LinkedHashSet implements the interface and SortedSet extends it. For such a set, the reversed() method will return a reversed view of it.

SequencedSet<String> set = new LinkedHashSet<>(List.of("A", "B", "C"));
SequencedSet<String> reversedSet = set.reversed();
System.out.println(reversedSet); // [C, B, A]
M. Justin
  • 14,487
  • 7
  • 91
  • 130