Найти сообщения от определенного ключа до определенного ключа, в то время как возможность удалить устаревшие ключи - PullRequest
4 голосов
/ 13 мая 2010

Моя проблема

Допустим, я хочу хранить свои сообщения в какой-то структуре данных для приложения с длинным опросом:

1. "dude"
2. "where"
3. "is"
4. "my"
5. "car"

При запросе сообщений из индекса [4,5] должно возвращаться: "my","car".

Далее давайте предположим, что через некоторое время я хотел бы удалить старые сообщения, потому что они больше не нужны, и я хочу сэкономить память. Допустим, через время x сообщения [1-3] устарели. Я предполагаю, что было бы наиболее эффективно просто удалять один раз каждые x секунд. Следующая моя структура данных должна содержать:

4. "my"
5. "car"

Мое решение?

Я думал об использовании карты concurrentskiplistset или concurrentskiplist. Также я думал об удалении старых сообщений изнутри newSingleThreadScheduledExecutor. Я хотел бы знать, как бы вы реализовали (эффективно / поточно-ориентированно) это или, возможно, использовали бы библиотеку?

Ответы [ 2 ]

2 голосов
/ 14 мая 2010

Большая проблема, насколько я понимаю, состоит в том, как позволить определенным элементам истечь через некоторое время. У меня было похожее требование, и я создал класс сообщений, в котором реализован интерфейс Delayed Interface . Этот класс содержал все, что мне было нужно для сообщения, и (через интерфейс Delayed) сообщал мне, когда оно истекло.

Я использовал экземпляры этого объекта в параллельной коллекции, вы можете использовать ConcurrentMap , потому что это позволит вам вводить эти объекты с помощью целочисленного ключа.

Время от времени я собирал коллекцию, убирая предметы, задержка которых прошла. Мы проверяем срок действия с помощью метода getDelay интерфейса Delayed:

message.getDelay(TimeUnit.MILLISECONDS);

Я использовал обычный поток, который некоторое время спал, а затем собирал устаревшие элементы. В моих требованиях не было важно, чтобы элементы были удалены, как только истек срок их задержки. Кажется, у вас есть аналогичная гибкость.

Если вам нужно было удалить элементы, как только истечет время их задержки, тогда вместо того, чтобы спать в течение заданного периода времени в вашем потоке, вы будете спать в ожидании задержки сообщения, которое истечет первым.

Вот мой класс отложенных сообщений:

class DelayedMessage implements Delayed {

    long endOfDelay;
    Date requestTime;
    String message;

    public DelayedMessage(String m, int delay) {
        requestTime = new Date();
        endOfDelay = System.currentTimeMillis()
                + delay;
        this.message = m;
    }

    public long getDelay(TimeUnit unit) {
        long delay = unit.convert(
                endOfDelay - System.currentTimeMillis(),
                TimeUnit.MILLISECONDS);
        return delay;
    }

    public int compareTo(Delayed o) {
        DelayedMessage that = (DelayedMessage) o;
        if (this.endOfDelay < that.endOfDelay) {
            return -1;

        }
        if (this.endOfDelay > that.endOfDelay) {
            return 1;
        }
        return this.requestTime.compareTo(that.requestTime);
    }

    @Override
    public String toString() {
        return message;
    }
}
2 голосов
/ 13 мая 2010

Я не уверен, что это то, что вы хотите, но, похоже, вам нужен NavigableMap<K,V> для меня.

import java.util.*;
public class NaviMap {
    public static void main(String[] args) {
        NavigableMap<Integer,String> nmap = new TreeMap<Integer,String>();
        nmap.put(1, "dude");
        nmap.put(2, "where");
        nmap.put(3, "is");
        nmap.put(4, "my");
        nmap.put(5, "car");

        System.out.println(nmap);
        // prints "{1=dude, 2=where, 3=is, 4=my, 5=car}"        

        System.out.println(nmap.subMap(4, true,  5, true).values());
        // prints "[my, car]"              ^inclusive^  

        nmap.subMap(1, true, 3, true).clear();
        System.out.println(nmap);
        // prints "{4=my, 5=car}"

        // wrap into synchronized SortedMap
        SortedMap<Integer,String> ssmap =Collections.synchronizedSortedMap(nmap);

        System.out.println(ssmap.subMap(4, 5));
        // prints "{4=my}"                 ^exclusive upper bound!

        System.out.println(ssmap.subMap(4, 5+1));
        // prints "{4=my, 5=car}"          ^ugly but "works"
    }
}

Теперь, к сожалению нет простого способа получить synchronized версию NavigableMap<K,V>, но SortedMap имеет subMap, но только одну перегрузку, где верхняя граница строго эксклюзив.

API ссылки

...