7

I'm looking for a Java library class which provides a similar interface to this:

void addData(Comparable data);
int countBiggerThan(Comparable data);
void removeSmallerThan(Comparable data);

I would like to use it to make sure that in the last 10 minutes/hour/day there were no more than n actions. For examaple:

timeWindow = now() - 1 hour;
if (counter.countBiggerThan(timeWindow) < n) {
    doSomething();
    counter.addData(now());
}
counter.removeSmallerThan(timeWindow);

It wouldn't be too complicated to write one but I'd not want to reinvent the wheel. I guess there is something similar in one of the well-known Java libraries but I haven't found anything useful yet.

3 Answers 3

4

This task is too simple to carry a dependency for:

class Counter<E extends Comparable<? super E>> {
    private TreeSet<E> set = new TreeSet<>();

    public void addData(E e) {
       set.add(e);
   }

   public int countBiggerThan(E e) {
       return set.tailSet(e).size();
   }

   public void removeSmallerThan(E e) {
       set.headSet(e).clear();
   }
}

Usage (with Joda Time):

Counter<DateTime> counter = new Counter<>();
counter.add(new DateTime());

counter.countBiggerThan(new DateTime().munusHours(1));

A bit more ugly with java.util.Date:

Counter<Date> counter = new Counter<>();
counter.add(new Date());

Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.HOUR_OF_DAY, -1);
counter.countBiggerThan(cal.getTime());

Or, if you alreadly use Java 8:

Counter<LocalDateTime> counter = new Counter<>();
counter.add(LocalDateTime.now());

counter.countBiggerThan(LocalDateTime.now().munusHours(1));
1
  • @winterblood you should understand that there is no interface with exactly the asked API in any library, and it is hard to imagine more thin wrapper to implement it than the wrapper over standard TreeSet I've showed. I could agree the question itself is off-topic here and more suitable for SO.
    – leventov
    Feb 13, 2014 at 7:41
0

Executors

The Executors built into Java can schedule a task to be run every so often with a guarantee the tasks won't be run sooner. So you won't run over that too-many-times goal of your Question.

ScheduledExecutorService

See specifically the ScheduledExecutorService. But be sure to understand the issue described humorously here; basically your Runnable should have a Try-Catch to catch all unexpected Exceptions.

Conversely, while you are guaranteed a maximum number of times, you are not guaranteed a minimum. If you want twice an hour for the task to run, that would mean every 30 minutes. But if one run of the task takes longer than 30 minutes, say 40 minutes, the ScheduledExecutorService waits until that task completes before scheduling the next run of the task. So in a given 60 minute period, you may have completed one or two runs, but no more than two.

-1

This sort of manipulation looks like a typical use-case for functional programming and could be realized by applying predicates to collections. Those will be introduced with Java 8 as a new language feature but for now I would look for a functional framework for Java 6/7:

  1. Guava offers some general purpose function interfaces and integrates them into their collection abstraction. For most projects, Guava is on the class path anyways, so this is usually a good option.

  2. Functional Java is a more complex implementation of this paradigm. I would only chose this option if you want to make use of other functional patterns throughout the application.

  3. Use a semi-functional language such as Scala for the code that requires this type of handling. Since these classes compile to Java byte code, they will integrate nicely with the rest of your Java application. This is probably the heaviest choice, but if you consider Scala in general, it is a very recommendable language.

Otherwise, you can of course just upgrade to Java 8, if this is an option, and use the new stream functionality.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.