Correct implementation of time based storage of objects - java

For a given task, I should store an object while keeping track of the time of its creation at least per day.
The easiest solution I could find is to use Calendar to set day of year based on time stamp of objects creation.
Here is the object in a simple form:
public class PhysicalActivity implements Serializable {
private long mTimestamp;
private int mYear;
private int mMonthOfYear;
private int mWeekOfYear;
private int mWeekOfMonth;
private int mDayOfYear;
private int mDayOfMonth;
private int mDayOfWeek;
public PhysicalActivity(long timestamp){
mTimestamp = timestamp;
Calendar c = Calendar.getInstance();
c.setTimeInMillis(mTimestamp);
c.setTimeZone(TimeZone.getDefault());
mYear = c.get(Calendar.YEAR);
mMonthOfYear = c.get(Calendar.MONTH);
mWeekOfYear = c.get(Calendar.WEEK_OF_YEAR);
mWeekOfMonth = c.get(Calendar.WEEK_OF_MONTH);
mDayOfYear = c.get(Calendar.DAY_OF_YEAR);
mDayOfMonth = c.get(Calendar.DAY_OF_MONTH);
mDayOfWeek = c.get(Calendar.DAY_OF_WEEK);
}
//Getters for all members...
}
Then I have this object that holds all instances in an List<PhysicalActivity>:
public class PhysicalActivityHolder implements Serializable {
private long mCreationTimestamp;
private long mLastUpdateTimestamp;
private List<PhysicalActivity> mList;
public PhysicalActivityHolder(long creationTimestamp) {
mCreationTimestamp = creationTimestamp;
if(mList == null) {
mList = new ArrayList<PhysicalActivity>();
}
}
public void addPhysicalActivity(PhysicalActivity pa){
if(mList == null) {
throw new NullPointerException("List is null");
} else {
mList.add(pa);
}
}
public List<PhysicalActivity> getPhysicalActivitiesForDayOfYear(int dayOfYear) {
List<PhysicalActivity> activities = null;
for(PhysicalActivity p : mList) {
if(p.getDayOfYear() == dayOfYear){
activities.add(p);
}
}
return activities;
}
//Some similar methods for getting list by month of year, week of year...etc...
}
Then whenever there is a new PhysicalActivity instance is coming, I read the PhysicalACtivityHolder from disk (deserialize), add the new instance to the List<> and then save (serialize) the Holder object again to the disk.
I hope that you got my point by now. I am afraid this is not going to be a good solution. one of the problems is what if the device's timestamps changes? then the whole idea will be ruined.
I would love to know how would you implement such task? what could be the better way of doing this?

First of all, while not related to the timestamp issue, an SQLite Database would seem like a much more appropriate medium to store this information. In particular:
You don't need to serialize and deserialize the whole collection every time.
You don't need to keep the whole collection in memory.
You can add, remove, or update single events.
You can easily query by year, month, &c using SQL SELECT statements.
About the "timestamp changing" part (unless you have an external, trusted data source for the time, such as a server), yes, the device's date or time may be manually changed. However, how big of a problem would that be? This data wouldn't seem to be critically dependent on having the exact time.

Related

Java Collection sort

I am trying to sort a list of Dates and it's not working.
Here is the declaration and get function in AttEnt
#Temporal(TemporalType.TIMESTAMP)
#Column(name = "end_time")
private Date endTime;
public Date getEndTime() {
return endTime;
}
Here is the sorting code that isn't doing anything. GetAttempts() gets the list of all the attempts for called. They aren't in order, and I just want to be able to get whatever attempt has the latest endTime.
List<AttEnt> attempts = called.getAttempts();
Collections.sort(attempts, new Comparator<AttEnt>() {
#Override
public int compare(AttEnt a1, AttEnt a2) {
if (a1.getEndTime() == null || a2.getEndTime() == null)
return 0;
return a1.getEndTime().compareTo(a2.getEndTime());
}
});
I believe that the code above should sort attempts, and then after it attempts should be sorted, so the latest end time would be attempts.get(attempts.size()-1).getEndTime()
Comparator<AttEnt> comparator = Comparator.comparing(AttEnt::getEndTime).reversed();
attempts.sort(comparator);
Java static methods in interfaces are your friend
Click HERE for more awesomeness

Related jobs in JSprit , One before another case : IllegalArgumentException

This question is related to this topic : Related jobs in JSprit
I'm trying to use the "one before another" constraint but i'm experiencing a java.lang.IllegalArgumentException: arg must not be null . It looks like Capacity cap2 is null when calculating Capacity max. I don't really understand why.
:(
Do you have an idea about this?
For the record, I'm on the 1.6.2 version. TY for your help.
String before = "2";
String after = "11";
final StateManager stateManager = new StateManager(problem);
stateManager.addStateUpdater(new JobsInRouteMemorizer(stateManager));
ConstraintManager constraintManager = new ConstraintManager(problem, stateManager);
constraintManager.addConstraint(new OneJobBeforeAnother(stateManager, before, after));
final RewardAndPenaltiesThroughSoftConstraints contrib = new RewardAndPenaltiesThroughSoftConstraints(problem, before, after);
SolutionCostCalculator costCalculator = new SolutionCostCalculator() {
#Override
public double getCosts(VehicleRoutingProblemSolution solution) {
double costs = 0.;
List<VehicleRoute> routes = (List<VehicleRoute>) solution.getRoutes();
for(VehicleRoute route : routes){
costs+=route.getVehicle().getType().getVehicleCostParams().fix;
costs+=stateManager.getRouteState(route, InternalStates.COSTS, Double.class);
costs+=contrib.getCosts(route);
}
return costs;
}
};
VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(problem,
"algorithmConfig.xml");
vraBuilder.addCoreConstraints();
vraBuilder.setStateAndConstraintManager(stateManager, constraintManager);
vraBuilder.addDefaultCostCalculators();
vraBuilder.setObjectiveFunction(costCalculator);
algorithm = vraBuilder.build();
public class JobsInRouteMemorizer implements StateUpdater, ActivityVisitor {
private StateManager stateManager;
private VehicleRoute route;
public JobsInRouteMemorizer(StateManager stateManager) {
super();
this.stateManager = stateManager;
}
#Override
public void begin(VehicleRoute route) {
this.route=route;
}
#Override
public void visit(TourActivity activity) {
if(activity instanceof JobActivity){
String jobId = ((JobActivity) activity).getJob().getId();
StateId stateId = stateManager.createStateId(jobId);
System.out.println(stateId.getIndex());
System.out.println(stateId.toString());
stateManager.putProblemState(stateId, VehicleRoute.class, this.route);
}
}
#Override
public void finish() {}
}
Short answer: You cannot create StateId instances on the fly. All StateId instances have to be generated before the algorithm is run. See longer answer for why doing this is still not a good idea and you should consider a redesign.
Analysis: I ran into the same problem and traced it back to the way StateId instances are created in StateManager:
public StateId createStateId(String name) {
if (createdStateIds.containsKey(name)) return createdStateIds.get(name);
if (stateIndexCounter >= activityStates[0].length) {
activityStates = new Object[vrp.getNuActivities() + 1][stateIndexCounter + 1];
vehicleDependentActivityStates = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter + 1];
routeStatesArr = new Object[vrp.getNuActivities()+1][stateIndexCounter+1];
vehicleDependentRouteStatesArr = new Object[nuActivities][nuVehicleTypeKeys][stateIndexCounter+1];
problemStates = new Object[stateIndexCounter+1];
}
StateId id = StateFactory.createId(name, stateIndexCounter);
incStateIndexCounter();
createdStateIds.put(name, id);
return id;
}
Each time you create a new StateId and there is no more space available for states the old state arrays are overwritten with a longer version to make space for your new state (at start there is space for 30 StateIds, a few already used by JSprit itself). As you can see, the old elements aren't copied over, so what happens here is a race condition between UpdateLoads, which sets the state used as cap2, your code, which generates a new StateId and overwrites the current state and UpdateMaxCapacityUtilisationAtActivitiesByLookingForwardInRoute which reads the state (that doesn't exist anymore).
Given that this code only extends the arrays by one it is very inefficient to have many StateIds, as for each new StateId all arrays have to be recreated. To mitigate this I used only one StateId in my code and stored a Map<String, VehicleRoute> in it:
Map<String, VehicleRoute> routeMapping = Optional.ofNullable(stateManager.getProblemState(stateId, Map.class)).orElse(new ConcurrentHashMap<>())
This way you don't run out of StateId instances and can still store relations between an unlimited number of jobs.

Java: counting number of times data appears in a class

I know how to count most things when it comes to Java, but this has either stumped me a lot, or my brain is dying. Anyway, I have a class called "Jobs", and within that class is a String variable called "day". Multiple new Jobs have been created already (exact number is unknown), and now I need to query and find out how many Jobs are on x day. I assume it would be easy enough with a while loop, but I don't know how to create one that looks through Jobs as a whole rather than one specific one.
The Job data was created by reading a file (the name of which is jobFile) via a Scanner.
public class Job_16997761 {
private int jobID; // unique job identification number
private int customerID; // unique customer identification number
private String registration; // registration number for vehicle for this job
private String date; // when the job is carried out by mechanic
private String day; // day of the week that job is booked for
private double totalFee; // total price for the Job
private int[] serviceCode; // the service codes to be carried out on the vehicle for the job
//Constructor
public Job_16997761(int jobID, int customerID, String registration,
String date, String day, double totalFee, int[] serviceCode) {
this.jobID = jobID;
this.customerID = customerID;
this.registration = registration;
this.date = date;
this.day = day;
this.totalFee = totalFee;
this.serviceCode = serviceCode;
}
Not sure why you are creating a dynamic instance of a job (eg. Job_16997761, it seems that each job has its own class). But when creating the jobs you can maintain a map that will have the number of jobs per day. Something like:
Map<String, Long> jobsPerDay=new HashMap<String,Long>();
Then when creating a new job you can simply increment the counter for each day:
jobsPerDay.put(day,jobsPerDay.get(day)!=null?jobsPerDay.get(day)++:1);
This way you will be able to get the number of jobs for a day by using: jobsPerDay.get(day)
Please note that you can use java.time.DayOfWeek instead of a String.
It's hard to tell you correct solution unless you give more details. You are saying you can write while loop so I will assume you have a collection of Job already.
int count = 0;
List<Job> jobs = readJobsFromFile();
for(Job job : jobs) {
if(job.getDay().equals(inputDay)){ //inputDay is day you have to find number of jobs on.
count++;
}
}
System.out.Println(count);
This is just one of the many ways and may not be that efficient, but this is one way you may consider (Before you edited your last post). Using an arrayList to contain all the Job objects and iterate through the objects.
import java.util.*;
public class SomeClass {
public static void main(String[] args)
{
Jobs job1 = new Jobs(1);
Jobs job2 = new Jobs(1);
Jobs job3 = new Jobs(2);
Jobs job4 = new Jobs(2);
Jobs job5 = new Jobs(2);
ArrayList<Jobs> jobList = new ArrayList<Jobs>();
jobList.add(job1);
jobList.add(job2);
jobList.add(job3);
jobList.add(job4);
jobList.add(job5);
System.out.println(numOfJobOnDayX(jobList, 2)); //Jobs which falls on day 2
}
public static int numOfJobOnDayX(ArrayList<Jobs> jobList, int specifiedDay)
{
int count=0;
for(int x=0; x<jobList.size(); x++) //May use a for-each loop instead
if(jobList.get(x).days == specifiedDay)
count ++;
return count;
}
}
OUTPUT: 3
Class for Jobs..
class Jobs
{
int days;
public Jobs(int days)
{
this.days = days;
}
}
For simplicity, I am not using any getter and setter methods. You may want to think about what data structure you want to use to hold your objects. Once again, I need to re-emphasize this may not be an efficient way, but it gives you some ideas some possibilities of doing the count.

Sorting a complete HashMap

I am trying to work with a seemingly complex HashMap object to pupulate my expandable Listview in android.
The generic parameters for my HashMap as as shown below:
//HashMap<Map<YEAR,MONTH>,List<DAYS>>
HashMap<Map<Integer,Integer>,List<Integer>
I am using the Hash map to monitor day, month and year when an event took place. So assuming an event took place on 12th, 20th and 25th in May 2013, I would do something as this:
HashMap<Integer,Integer>,List<Integer>> events = new HashMap<Integer,Integer>,List<Integer>();
HashMap<Integer,Integer> yearMonth = new HashMap<Integer,Integer>();
yearMonth.put(2013,5);
events.put(yearMonth,Arrays.asList(new Integer[]{12,20,25}));
I have created an adapter for my expandable list view and it displays fine as shown below. Now I want to be able to sort the above HashMap, first by Year and Month so that my listview will display events in 2014 at the top following by 2013, 2012 .... in that order.
Is this possible?
Thanks.
Well, I just read "sort a hasmap". In the case you really want sort your data, a hashmap is definitely the wrong one.
Maybe you should think about using a linkedlist...
Create your own class instead of the hashmap, and adjust the adapter to suit those objects.
Then you can implement your own sorting, by implementing Comparable and creating a compareTo() method in your class.
This gives you all the control you need. For example:
public class myEvent implements Serializable, Comparable<myEvent>
{
private Integer day;
private Integer month;
private Integer year;
public myEvent( Integer day, Integer month, Integer year, <your other data> )
{
// Save the stuff here
this.day = day;
this.month = month;
this.year = year;
}
// Create getDay(), getMonth(), getYear() methods for each parameter
public int compareTo( myEvent another )
{
// Here, compare the two events year by year, month by month, and day by day
if ( this.year.compareTo( another.getYear() ) == 0 )
{
if ( this.month.compareTo( another.getMonth() ) == 0 )
{
return this.day.compareTo( another.getDay() );
} else {
return this.month.compareTo( another.getMonth() );
}
} else {
return this.year.compareTo( another.getYear() );
}
}
}
EDIT: When you want to sort a list of those myEvent objects, you can use the Collection api to make use of the Comparable implementation:
List<myEvent> allevents = new ArrayList<myEvent>();
// Add to the list
...
// Now sort it.
Collections.sort( allevents );
Good luck.

NullPointer in an Class array

I have two java classes. Schedule is the main class that uses an array of Jobs called deadline. I'm having problems putting anything in array. I have a for loop that reads data from a text file (it works fine) and inserts certain data into deadline. I not successfully creating deadline because whenever I want to start inserting into the array I get a NullPointerException. (The code below the ... obviously isn't what I actually coded, but it is still the same situation.)
It has been a while since I've coded in Java, so I might be just overlooking something simple, but I'm not really sure what it could be... Thanks for any help you can give.
public class Schedule {
private Job []deadline;
Schedule (int n){
Job[] deadline = new Job[n];
}
...
int n = 7;
Schedule schedule = new Schedule(n);
deadline[0] = new Job("A",3,40); // This line won't compile. NullPointerException
}
public class Job {
private String name;
private int deadline;
private int profit;
Job(String n, int d, int p){
name = n;
deadline = d;
profit = p;
}
}
You are shadowing deadline in your constructor, so you don't initialize the class member deadline, but the local one. Change it to:
private Job []deadline;
Schedule (int n){
deadline = new Job[n];
// ^^ note - no Job[] here
}

Categories

Resources