Luis Sep
Luis Sep

Reputation: 2402

Data structuring - Is there a better alternative to Map<Integer, List<List<Date>>>?

I need to organize some data into date ranges. I have a series of identifiers, and each of them has some date ranges for which it is active. Date ranges consist of a beginning and end date, which I will save in a List of two Date elements. So in the end, I have a Map<Integer, List<List<Date>>>, which looks a bit cumbersome. Is there any better way of saving this information?

Upvotes: 1

Views: 177

Answers (4)

Harald K
Harald K

Reputation: 27054

I suggest using the following, which both looks better (subjective) and is more correct domain-wise:

Map<Integer, List<DateRange>>

Where DateRange could simply be:

public class DateRange {
  Date start;
  Date end;
}

(Modify qualifiers and add getters/setters/methods as you see fit)

Bonus tip: Also, I'd like to point out that for most real-world date tasks, java.util.Date and java.util.Calendar is hard to use and isn't always well-defined. I suggest you consider using Joda time. Which just happens to have an Interval class that should work well for your scenario.

Upvotes: 0

roundar
roundar

Reputation: 1713

Here's a solution if you not interested in including guava or apache.

public class DateRange {

    private final Date start;
    private final Date end;

    public DateRange(Date start, Date end) {
        this.start = start;
        this.end = end;
    }

    public boolean contains(Date date) {
        // Use whatever comparison method is best 
        // for your particular date objects here
        return date.compareTo(start) >= 0 && date.compareTo(end) <= 0);
    }


    // Getters, Setters if applicable, etc.
}

Now Map<Integer, List<DateRange>> Seems very easy to read. To break it up even more, you can create an Identifier class like Rene Links's answer suggests, and just replace the apache commons Range with a list of your DateRanges like so:

public class Identifier {

    private final int id;
    private final List<DateRange> ranges;

    public Identifier(in id, List<DateRange> ranges) {
        this.id = id;
        this.ranges = ranges;
    }


    public boolean isActive(Date date) {
         for(DateRange dr : ranges) {
             if(dr.contains(date)) {
                 return true;
             }
         }
         return false;
    }

Upvotes: 0

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 135992

You can try guava MultiMap

ListMultimap<Integer, List<Date>> mm  = LinkedListMultimap.create();

Upvotes: 1

Beryllium
Beryllium

Reputation: 12988

Generally speaking you could split it into classes:

class A {
  Date from;
  Date until;
}

class B {
  List<A> list = ...
}

class C {
  List<B> list = ...
}

of course with meaningful names. So you can use C in your map.

You are probably going to have methods on each class level anyway, so later on you don't need to worry about the location of these methods - they just fit nicely into this structure, too.

Upvotes: 0

Related Questions