0

I have a set declared as follows

Set<String> orderSet = new LinkedHashSet <String>();

The String values stored are a combination of date and time convention

orderSet.add(bean.getDate()+"," + bean.getTimeConvention());

I always get the output as insertion order and that is why the linkedHashSet is designed for

I need the output to be in reverse order so that the latest date comes first?

i have heard of NavigableSet but it doesn't work well for my scenario .. Any suggestions?

thanks

jaggs
  • 298
  • 2
  • 9
  • 28
  • 2
    _"i have heard of NavigableSet which can only be used only for integer elements"_ Where did you heard that? – Alexis C. May 18 '14 at 13:52
  • 2
    NavigableSet <- It takes everything – Marco Acierno May 18 '14 at 13:56
  • I tried an example using descendingSet() with integer as elements.It works fine.But with String , i get an undefined error..So i was in such a conclusion.Sorry if it doesn't hold true .. – jaggs May 18 '14 at 14:00
  • Use a `TreeSet` and an appropriate `Comparator` – fge May 18 '14 at 14:01
  • I should also point out [Java LinkedHashSet backwards iteration](http://stackoverflow.com/q/10741902/289086) –  May 18 '14 at 15:29

5 Answers5

2

According to javadoc the purpose of a Set is to eliminate duplicates in a collection of elements. In order to reverse the elements of a collection you need to create a List first. Here is the example:

ArrayList<String> list = new ArrayList<String>(orderSet);
Collections.reverse(list);
2

The LinkedHashSet is ordered by insertion order. In cases where you are getting things in order (say from a query in a database) this maintains the order you get them and provides you with O(1) lookup into that (compared with the O(log n) for a TreeSet). Its also useful for when the ordering of the objects isn't something that is easily comparable.

The LinkedHashSet is also particularly useful for caches (see also its kin the LinkedHashMap which provides a method for removeEldestEntry which can be used to implement an LRU cache (evicting objects to maintain only the 100 (or whatever its configured for) most recently used items).

However, the LinkedHashSet is not a subclass of the interface NavigableSet. This means that a number of tools for manipulating the set are not there. To reverse the NavigableSet, you can get the descendingIterator() or descendingSet(). There are other bits in there like being able to get the next highest value of something, or the subset from one point to another.

There are two classes that implement the NavigableSet: ConcurrentSkipListSet (which uses a skip list) and TreeSet (which uses a red black tree).

The requirement for a NavigableSet is that the elements have an ordering to them (as implemented by Comparable. These include String, Date, as well as various number classes, and a whole bunch more... or for that matter, anything that you implement Comparable.

Note that these are all sets which means that there is only one copy of an element in the structure. If you are actually after a List with multiple copies, then you've got your Lists to work from. These are different tools for different purposes.

  • As a note, *personally* I like the SkipList. Its a neat data structure that is implemented under neath with linked lists. This makes doing things like iterating over the elements a much simpler approach (you just use the 'bottom' list) rather than messing with TreeSet's recursion. –  May 18 '14 at 14:28
1

This is how I would do it:

import java.util.Date;
import java.util.Map;
import java.util.NavigableSet;
import java.util.TreeSet;

public class DescendingSetTest {
    public static void main(String[] args) {        
        NavigableSet<Map.Entry<Date, String>> set = new TreeSet<Map.Entry<Date, String>>();

        set.add(newEntry(new Date(0), "0000"));
        set.add(newEntry(new Date(700000000000l), "0000"));
        set.add(newEntry(new Date(700000000000l), "9999"));

        for (Map.Entry<Date, String> entry : set.descendingSet())
            System.out.println(entry);
    }

    public static <K extends Comparable<? super K>, V extends Comparable<? super V>> Map.Entry<K, V> newEntry(K key, V value) {
        return new Entry<K, V>(key, value);
    }

    private static class Entry<K extends Comparable<? super K>, V extends Comparable<? super V>> implements Map.Entry<K, V>, Comparable<Entry<K, V>> {
        private K key;
        private V value;

        Entry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public int compareTo(Entry<K, V> that) {
            int c = key.compareTo(that.key);
            return c != 0 ? c : value.compareTo(that.value);
        }

        @SuppressWarnings("unchecked")
        @Override
        public boolean equals(Object that) {
            return that instanceof Entry<?, ?> ? compareTo((Entry<K, V>)that) == 0 : false;
        }

        @Override
        public String toString() {
            return key + "," + value;
        }
    }
}
pscuderi
  • 1,554
  • 12
  • 14
  • Why not just use a TreeSet and a Comparator instead? – Chetan Kinger May 18 '14 at 14:43
  • The idea was to solve it generically. But yes, you could also make a method that returns a generic comparator. However, I generally prefer something like this because then the entries can be easily printed and compared outside of the set. – pscuderi May 18 '14 at 14:48
1
for (Object o : linkedHashSet.reversed()) {
  System.out.println(o);
}

JEP 431: Sequenced Collections (release 9/19/23) in Java 21 has a reversed() method to LinkedHashSet. This reversed view of the LinkedHashSet can iterate in descending order.

M. Justin
  • 14,487
  • 7
  • 91
  • 130
A_Arnold
  • 3,195
  • 25
  • 39
0

LinkedHashMap orders elements by insertion order or by last access order. For a set with sorted elements, a SortedSet or its subclass NavigableSet is often a better fit.

You stated that NavigableSet doesn't work well for your scenario. It's hard to judge the correctness of that statement without details. Just in case it actually works for you or others reading this question, here's what it would look like:

Set<String> orderSet = new TreeSet<>(Comparator.reverseOrder());
orderSet.add(bean.getDate()+"," + bean.getTimeConvention());
M. Justin
  • 14,487
  • 7
  • 91
  • 130