Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

implementing time based queue for hashmap

I am working on an application where i need to have a fixed length for a HashMap. Initially the hashmap was restricted based on size so i used removeEldestEntry method of LinkedHashMap to achieve that.

Code:

public class FixedLengthHashMap<K,V> extends LinkedHashMap<K,V> {

    long max_length;

    public FixedLengthHashMap(long max_length){

        this.max_length = max_length;
    }

    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {

        return this.size() > max_length;
    }
}

But now I need to store entries on that HashMap based on time. Example if hashmap size is two weeks, the hashmap should have entries inserted for first 14 days and when a new entry is being inserted on 15th day, it should remove entries of 1st day. And on 16th day, all entries of 2nd say should be deleted and so on.

I tried removeEldestEntry method again like below:

public class FixedTimeHashMap<K,V> extends LinkedHashMap<K,V> {
    LocalDateTime start;
    public FixedTimeHashMap(){
        this.start = LocalDateTime.now();
    }
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest)
    {
        LocalDateTime current= LocalDateTime.now();
        Long diff = ChronoUnit.SECONDS.between(start, current);
        if(diff>60*60*24*14)
            return true;
        else
            return false;
    }
}

But this will only delete one entry for each insertion after the 14th day. I have to delete all entries of 1st day when new entry is inserted on the 15th day.

If you can give some advice or suggestions it will be very helpful. Thanks in advance.

like image 821
sparker Avatar asked May 24 '26 16:05

sparker


1 Answers

A LinkedHashMap would be a nice starting point, as it maintains the order of insertion. The value needs to have a date, so maybe wrap the original value in some class with a date, or require an interface.

static class Dated<V> {
    public final LocalDate date = LocalDate.now();
    public final V value;
    public Dated(V value) {
        this.value = value;
    }
}

Map<K, Dated<V>> map = new LinkedHashMap<>();

void insert(K key, V value) {
    Dated<V> datedValue = new Dated<>(value);
    LocalDate earliest = datedValue.date.minusDays(14);

    Iterator<Map.Entry<K, Dated<V>> it = map.entries().iterator();
    while (it.hasNext() && it.next().getValue().date.isBefore(earliest)) {
         it.remove();
    }

    map.remove(key); // So at the end of the linked list.
    map.put(key, datedValue);
}

The remove ensures that the latest addition is added at the end of the linked list, even if the key already existed.

Hence the iteration starts with the oldest elements, and deletes those.

Note: The question asked for a removeEldestOnes, based on the current time. That means when nothing is inserted, one could still remove old entries of more than 14 days in the past.

My code could be used for that too, but first doing map.remove on insert is essential, hence the integrated insert.

Making a custom collection class I leave to the OP.

like image 99
Joop Eggen Avatar answered May 27 '26 05:05

Joop Eggen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!