Looking for adequate Data Structure (Collection, Map, LocalDateTime) - java

I want a data structure that contain the following:
Two Objects that represent a timeslot (e.g. LocalDateTime in Java 8)
A boolean variable
The Timeslot needs to be connected to a boolean. The program needs to know if a timeslot is available. It will be used in a knapsack problem solving algorithm for work scheduling.
What I've got so far:
ArrayList<Map<List<LocalDateTime>, Boolean>>
But it looks pretty complicated and a Map might not be the best way to iterate through if I don't know the key. I tought about a ArrayList instead of a Map but I don't know how to initialize it with different Data Types.

Table from Google Guava sounds like a perfect fit for this.
Table<LocalDateTime, LocalDateTime, Boolean> dateTable
= TreeBasedTable.create();
The reason for it is that it gives you access to row, column, and value (in parameter order), and will allow you to do relatively straightforward lookups.
An example: If you want to find all of the values for a given LocalDateTime row, then you would do this:
LocalDateTime today = LocalDateTime.of(2014, Month.JULY, 26, 0, 0);
// prints a map of all of today's values
System.out.println(dateTable.row(today));

Related

container or data structure suitable to hold millisecond data

What would be a good data structure in Java to hold millisecond price data?
About 1.000.000 elementsor more in the container.
What is the specific container (vector, array, hash, etc) specifically designed to to hold a lot of data.
I do not intend to filter or sort the data but I do need the ability to assign a key (possibly a tie stamp) to get the corresponding price.
If you need to assign a value (price) to a key (price), you should use a collection implementing the Map interface: TreeMap, HashMap, Hashtable or LinkedHashMap. You can find an overview of the collections here.
If a key can have more than one value, you will need a Multimap, i.e. a map where the value is a collection (see an example here).
Assuming it is not the case, I'd suggest to use a TreeMap, i.e. a map where keys are sorted. Here is an example:
Map<Long, Double> priceHistory = new TreeMap<>();
ZonedDateTime zdt1 = ZonedDateTime.now();
ZonedDateTime zdt2 = ZonedDateTime.of(
LocalDate.of(2015,9,26),
LocalTime.of(11,10,9),
ZoneId.systemDefault());
priceHistory.put(zdt1.toInstant().toEpochMilli(), 10.5);
priceHistory.put(zdt2.toInstant().toEpochMilli(), 11.5);
It should not be a problem to hold 1 million elements and it should be fast to get the price for a given time stamp.
You probably don't really need millisecond precision, you just need to be able to get something for any given millisecond. Guava's RangeMap is great for this, you can construct a RangeMap<LocalDateTime, Price> and populate it with a value per second (for instance) with Range.closedOpen(second, second.plusSeconds(1)) as the key. You can then call .get() on an arbitrary LocalDateTime and it will return the value associated with the Range containing that time. You get arbitrary lookup precision but only use as much storage as you care to.
If you really do want millisecond precision you're going to have a hard time storing anything more than a few days of data efficiently. Instead you should look into storing your data in a database. Databases are designed to efficiently store and query large datasets, far beyond what standard in-memory data structures are designed for.

Organize objects by date range in Java

I have a List of Stat objects and each Stat has a Date field. This list may be very large. What I would like to do is organize these objects into date ranges (weeks to be specific) efficiently. So, if two objects occur in the same week, they go into the same List. For simplicity, the 'week' intervals are already defined so you don't have to worry about coming up with the ranges.
So here is my current approach. I have a LinkedHashMap<Date, List<Stat>> that contains all the dates I need in ascending order and each entry is initialized with an empty ArrayList. I am thinking for each Stat, iterating through the entire entrySet of the Map, and keeping track of the closest Date that the stat is also greater than or equal to. Then it would be something like map.get(closestDate).add(stat).
It seems like there should be a better way to do this. Perhaps create something like a findClosestKeyGreaterThanOrEqualTo so that I don't have to iterate through the entire map every time?
Any ideas?
You can make use of a NavigableMap (like TreeMap) which has very useful methods exactly for this purpose.
Initialize your map with all the values that you have computed and empty lists for each:
NavigableMap<Date, List<Stat>> map = new TreeMap<>();
// add all your weekly values associated with empty lists
Then for each of your Stat objects, find the proper list simply by:
final Entry<Date, List<Stat>> entry = map.floorEntry(stat.getDate());
entry.getValue().add(stat);
Thanks for your answers.
I am going to go with a NavigableMap as the floorKey function is exactly what I need.
Here is what I would do, assuming you can already convert Date into a weekId:
Create a Map<WeekId, List<Stat>>
Iterate through your original List<Stat> once and in each cycle calculate weekId from the date, then add Stat to an appropriate List by retrieving it from the Map by weekId (create one if it does not exist and add it to the map)
You should have a desired result in the map at the end of the loop.
Make sure all dates are rounded to the nearest week. Then use a getWeek(stat) function and insert the stat into the map there. A simple HashMultimap will do.
You need to deal with the issue of hash codes and equality. Say I have a data type
class Pair {
public int x;
public int y;
// obvious constructor
}
Observe:
new Pair(1,2) == new Pair(1,2) // false
new Pair(1,2).equals(new Pair(1,2)) // false
And if you use them as keys in a hash map they will be different keys.
You need to override equals and hashCode to overcome this.
For Date we observe:
public boolean equals(Object obj) {
return obj instanceof Date && getTime() == ((Date) obj).getTime();
}
Hashcode will be defined correspondingly. So if you key off of Date you will only get what you want if the dates agree to the milliscecond.
Therefore a
HashMultimap<Date, Stat> map;
Is fine, but you should programmatically observe the convention that all dates are rounded down to the nearest week. Then do:
Date key = roundToWeek(stat);
map.insert(key, stat);
And you should be good.

How to search between two dates in a text file??? HASH MAP?

For example I have the following file
B 01-02-2013 1233
B 03-02-2013 129
B 04-02-2013 13
the date is stored as a String from user input. The next number is a integer for "CaloriesBurnt"
I want to if given a start date and end date. CALCULATE TOTAL CALORIES BURNED between those two dates. So for example here I would want to total the calories from 01-02-2013 TO 04-02-2013. So i need to pull the calories for the dates inbetween that period. I Know I have to convert to date format and then perhaps use a HASP MAP? to order?? any help really is appreciated
The best data structure in that situation is a TreeMap. It maintains its keys sorted, and has methods returning a "submap" containing all the entries between two key values.
If each date is unique, you can use a TreeMap<Date, Record>. If not, then use a TreeMap<Date, List<Record>> (Record being the class used to hold all the elements of one line of your file).
Once you have the submap, you just need to iterate on all the values and sum their calories.
First of all I would parse the whole text file into objects. No matter how the date is. Each line in the text file could be something like this (of course with setters and getters and public/private and all this stuff ;):
class Entry {
Date date;
int calories;
}
Parse the text file and create a list of such objects. Then you could operate on this list. You can sort it (with a sorter-object written by you), you can search it or do what ever you want. Once you get rid of the actual text file and you have objects, it gets much easier. You can even use some third-party libraries to easily compute statistics (e.g. the average, max values or such things).
You might probably want to use a sorted collection like a SortedMap<Date, UserData> ( UserData would represent whatever data you want to store in the map), then use subMap(startDate, endDate + 1 day) to extract period. Note that endDate + 1 day is needed since the upper bound is exclusive.
Example:
SortedMap<Date, Integer> caloriesByDate = new TreeMap<>(); //we only store the calories
... //fill here
SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy");
//get entries in the interval `[01-02-2013,03-02-2013]`.
caloriesByDate.subMap( f.parse("01-02-2013"), f.parse("04-02-2013") );

Sorting 1,000,000 Objects (not by Key) - Java

I have c.1,000,000 objects that need to be stored in some form of data structure. They must be unique by a key (ID) - but sorted according to their date. I'm therefore trying to think of a best way of storing them in some form of data structure.
Performance (in terms of time taken to execute) it the primary goal, and then memory usage. My idea was to put the objects into a Tree, so they may be sorted according to their date as they enter the data structure, and I can then return them in order. However - I think this is going to be horrendously slow to find a single object based on it's ID. One thought that did occur to me was to have a secondary structure which linked ID's to dates so I can reduce the time taken to find the single object, or just store everything by this ID anyway (perhaps in a HashTable) and then just sort through all 1,000,000 objects when I want to return them (although this seems to take a very long time).
Key Points:
Objects may be added afterwards so the c.1,000,000 objects ARE NOT fixed. They WILL NOT be updated or removed.
I MAY NOT use Java's built in Comparator.
I am optimising for efficiency of returning the data - whether this be the complete set in order (by date), or a single object obtained from it's ID.
if performance in your chief concern before memory usage, i'd go with 2 datastructures:
ArrayList<YourClass> instancesByDate;
and
HashMap<SomeId,YourClass> instancesById;
this gives you the fastest traversal by date and O(1) lookup (depending on hashCode() obviously).
How about using a hashtable of ID => yourobject for the ID lookups, and a secondary hashtable of date (at some level of granularity) => Vector<yourobject>? You could choose the 'granularity' of the date to ensure you've a moderate number of objects in each vector - and sort each by date.

Hybrid between features of Queue and Map types

I understand that a queue is a collection type that is accessed through the head and/or tail.
I also understand that a map is a collection type the contains a number of unique keys, which each have an associated value.
What I need, is a map, with a fixed number of values, where the keys will be set once, and will not be changed after they are first set.
The hard part I can't get my head around is getting the values to act as a queue with a fixed length, which can be pushed, without affecting the key.
For example:
Initial collection (newest items at the top):
Key1, Value1
Key2, Value2
Key3, Value3
Collection after adding new value NewValue:
Key1, NewValue
Key2, Value1
Key3, Value2
So, I want the key to stay the same, and be able to add the new value, by pushing the oldest value off the end, and moving all other values further down towards the end.
If a type like this isn't available within the framework, could somebody please recommend a way to implement it.
Thank you!
EDIT:
An example of why I need to do this:
I need to be able to access the values
according to the time period it was
created in.
Example:
Key: 0 will contain a value from today
Key: -1 will contain a value from yesterday
Key: -2 will contain a value from two days ago
etc.
Only one value will be entered every
day, and one value will ALWAYS be
entered every day.
Sounds like you could use:
new LinkedHashMap<Long,V>(initialCapacity, loadFactor, false) {
protected boolean removeEldestEntry(Map.Entry<Long,V> e) {
return size() > MAX_ENTRIES;
}
};
To get or put items in this map you will need to canonicalize your timestamp, e.g., to 00:00:00.000 of the day.
An advantage of this approach is when the assumption that "one value will ALWAYS be entered every day" is violated it won't fail silently.
So, you're really talking about an index into an array.
I'd just wrap an 'ArrayList` in your object.
Your push method would also remove the "oldest" element from the end. You'd define methods such as getToday() and getPriorDay(numDaysBackFromToday)
However, you're using a lot of magic numbers there if you're not actually storing a date or a time with the data. You're hoping that the data has been loaded correctly.
Personally I'd use a timestamp associated with the data in a LinkedHashMap and iterate to find the one you want.
I've rethought my question with regards to the magic numbers, and have decided it'd be easier to use a predefined collection type with positive indexes. Then I'll simply make the push method drop the last item off the end when I reach the maximum number of values I need.
Then I'll get my class to interpret -1 as 1 to get the required value.
Thanks for your help, I was simply over-thinking things.

Categories

Resources