Bart Friederichs
Bart Friederichs

Reputation: 33573

How to get nth item from a TreeMap?

I have a TreeMap<Date, Integer> and I want to fetch the nth item from that map. What I came up with now is this:

((Integer)myTreeMap.values().toArray()[index]).intValue();

but this feels quite clunky, not to mention what is happening on the heap or with performance?

Is there a concise way to get the nth item from a TreeMap/SortedMap ?

Upvotes: 5

Views: 6326

Answers (4)

3rdRockSoftware
3rdRockSoftware

Reputation: 85

I have found a way of getting the Nth key / value from a Map. and that is simply to add a counter.

int count = 1;
for (Map.Entry entry : Map.entrySet())
        {
            if (count == 1) //the Nth value
            {
                System.out.println(count + " "
                     + entry.getKey() + " "
                     + entry.getValue());
            }
            count++;
        }

Upvotes: 0

krishna Prasad
krishna Prasad

Reputation: 3812

You can use steam and skip n-1 elements and take the first as below: tmap.entrySet().stream().skip(n-1).findFirst();. Details with data set examples:

TreeMap<Date, Integer> tmap = new TreeMap<Date, Integer>();
tmap.put(new Date(2014, 1, 1), 0);
tmap.put(new Date(2015, 1, 1), 1);
tmap.put(new Date(2016, 1, 1), 2);
tmap.put(new Date(2017, 1, 1), 3);
tmap.put(new Date(2018, 1,1 ), 4);

System.out.println(tmap);

// Let's find the nth elements i.e n = 3;
int n = 3;
System.out.println(" " + n + " elements: ");
System.out.println(tmap.entrySet().stream().skip(n-1).findFirst());

Output as follow:

{Sun Feb 01 00:00:00 IST 3914=0, Mon Feb 01 00:00:00 IST 3915=1, Tue Feb 01 00:00:00 IST 3916=2, Thu Feb 01 00:00:00 IST 3917=3, Fri Feb 01 00:00:00 IST 3918=4}
3 elements: 
Optional[Tue Feb 01 00:00:00 IST 3916=2]

Upvotes: 2

LppEdd
LppEdd

Reputation: 21172

Edit: an alternative is

final Optional<T> first =
        treeMap.values()
               .stream()
               .skip(index - 1)
               .findFirst();

if (first.isPresent()) {
    final T value = first.get();
}

What about

final List<T> values = new ArrayList<>(myTreeMap.values());
final T value = values.get(index);

T is just a generic type in place of your Map value type.
index is your nth element.

As pointed out, that's inefficient for large maps, as internally the ArrayList constructor the toArray method is called

public Object[] toArray() {
    // Estimate size of array; be prepared to see more or fewer elements
    Object[] r = new Object[size()];
    Iterator<E> it = iterator();
    for (int i = 0; i < r.length; i++) {
        if (! it.hasNext()) // fewer elements than expected
            return Arrays.copyOf(r, i);
        r[i] = it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}

Upvotes: 5

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522817

We can try using a stream here. In the snippet below, we create a sorted map with five entries. Then, we create a stream, skipping the first 3 elements, and using findFirst to capture the first element.

Map<Integer, String> myTreeMap = new TreeMap<>();
myTreeMap.put(1, "one");
myTreeMap.put(2, "two");
myTreeMap.put(3, "three");
myTreeMap.put(4, "four");
myTreeMap.put(5, "five");
String fourth = myTreeMap.entrySet().stream()
   .skip(3)
   .map(map -> map.getValue()).findFirst().get();
System.out.println("fourth value in map is: " + fourth);

Upvotes: 2

Related Questions