count the number of occurences for each hour in Java - java

First, sorry for my English who may be poor, I hope you will understand me
I do not see how to recover my object count per hour.
I hope you can help me find out more about my question.
I have a mission object that contains a mission list that each have as attribute
a STRING name and a STRING time (hhmmss format)
here is an example :
0 : name1 102101
1 : name2 102801
2 : name3 104801
3 : name4 110501
4 : name5 120301
I wish I could make an array allowing me to count the number of missions for each hour
In this example I would have :
10 => 3
11 => 1
12 => 1
I do not know if you see what I would like to get :)
If you ever have small tracks I'm interested
Thank you for reading me !
I wish you a good evening

TL;DR
As the comments mentioned, you may want to use a HashMap with String keys reflecting the hour and Integer values for the count (missions per hour).
Since you're dealing with hours, meaning that you have a maximum of 24 of them, you can also replace the HashMap with an Array of 24 items.
The Mission class
Basically, all is needed here is a getter for the time attribute. If you feel fancy, you can also add a getHour which will return the hour instead of the whole time string.
class Mission {
private String name;
private String time;
Mission(String name, String time) {
this.name = name;
this.time = time;
}
String getHour() {
// This gives us the 2 first characters into a String - aka the "hour"
return time.substring(0, 2);
}
}
Using the HashMap
We want to keep the count per hour in a HashMap. So we'll iterate over the missionsList and for each item, we'll get its count, then we'll increment it.
If the hour is not in the HashMap yet, we would normally receive a null. To handle that with minimal boilerplate, we'll use the getOrDefault method. We can call it like this map.getOrDefault("10", 0). This will return the missions count of hour 10, and if that count doesn't exist yet (which means we didn't add it to the map yet) we will receive 0 instead of null. The code will look like this
public static void main(String[] args) {
// This will built our list of missions
List<Mission> missionsList = Arrays.asList(
new Mission("name1", "102101"),
new Mission("name2", "102801"),
new Mission("name3", "104801"),
new Mission("name4", "110501"),
new Mission("name5", "120301")
);
// This map will keep the count of missions (value) per hour (key)
Map<String, Integer> missionsPerHour = new HashMap<>();
for (Mission mission : missionsList) {
// Let's start by getting the hour,
// this will act as the key of our map entry
String hour = mission.getHour();
// Here we get the count of the current hour (so far).
// This is the "value" of our map entry
int count = missionsPerHour.getOrDefault(mission.getHour(), 0);
// Here we increment it (by adding/replacing the entry in the map)
missionsPerHour.put(hour, count + 1);
}
// Once we have the count per hour,
// we iterate over all the keys in the map (which are the hours).
// Then we simply print the count per hour
for (String hour : missionsPerHour.keySet()) {
System.out.println(String.format(
"%s\t=>\t%d", hour, missionsPerHour.get(hour)
));
}
}

Related

Iterator between two given hours

I was in a job interview and got this question: " Write a function that gets 2 strings s,t that represents 2 hours ( in format HH: MM: SS ). It's known that s is earlier than t.
The function needs to calculate how many hours between the two given hours contains at most 2 digits.
For example- s- 10:59:00, t- 11:00:59 -
Answer- 11:00:00, 11:00:01,11:00:10, 11:00:11.
I tried to do while loops and got really stuck. Unfortunately, I didn't pass the interview.
How can I go over all the hours (every second is a new time) between 2 given hours in java as explained above? Thanks a lot
Java 8 allows you to use LocalTime.
LocalTime time1 = LocalTime.parse(t1);
LocalTime time2 = LocalTime.parse(t2);
The logic would require you to count the amount of different digits in a LocalTime, something like
boolean isWinner(LocalTime current) {
String onlyDigits = DateTimeFormatter.ofPattern("HHmmss").format(current);
Set<Character> set = new HashSet<>();
for (int index = 0; index < onlyDigits.length(); index++) {
set.add(onlyDigits.charAt(index));
}
return set.size() <= 2;
}
You can loop between the times like this
int count = 0;
for (LocalTime current = time1; current.isBefore(time2); current = current.plusSeconds(1)) {
if (isWinner(current)) {
count++;
}
}
That's it.
The question is really more geared towards getting a feel of how you'd approach the problem, and if you know about LocalTime API etc.

Create Global Multidimensional Array dynamically in Java

I have an Ordering System that comprises of a number of steps before the data is finally submitted and stored in the database. I have already completed and implemented the web version of the same Ordering System. Below is the Multidimensional Array in PHP that I created dynamically based on the below values.
In the first step of Order, a Plan is to be selected. Based on that plan, the total number of days will be decided.
Plan 1 - Days Served 26
Plan 1 - Meals Served Per Day 2
Plan 1 - Refreshments Served Per Day 2
Plan 2 - Days Served 5
Plan 2 - Meals Served Per Day 3
Plan 2 - Refreshments Served Per Day 0
and so on...
In the second step, starting date of the Order is to be selected. Weekends are to be excluded and only Weekdays will be counted as days served.
The PHP Multidimensional Array generated dynamically is below
Array
(
[Day 1] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
[Day 2] => Array
(
[meal_id_1] => Unique ID //to be replaced with user selection
[meal_code_1] => Meal Name //to be replaced with user selection
[meal_type_1] => Meal //prefilled based on the selected package
[meal_id_2] => Not Available //to be replaced with user selection
[meal_code_2] => 2 //to be replaced with user selection
[meal_type_2] => Meal //prefilled based on the selected package
)
In the above code, day number is added dynamically and numeric value in meal_id_1, meal_code_1 and meal_type_1 is also added dynamically.
To connect the App and Web Application logically, I want to post the selection from the App in similar Array.
Since I have Meals and Refreshments to be selected based on the plan, therefore I will be loading Meals for Day 1 and then based on the Plan selected Refreshments for Day 1. There will be 1 Activity for Meals, which be loaded with updated Day number and same for the Refreshments.
Using the below code, I am able to get the Unique ID of the Meals selected in an ArrayList.
int count = 0;
int size = list.size();
List<String> selected_meals = new ArrayList<String>();
for (int i = 0; i<size; i++){
if (list.get(i).isSelected()){
count++;
String selected_meal_string = list.get(i).getMeal_id();
selected_meals.add(selected_meal_string);
}
}
How can I transfer this selection to a Global Multidimensional Array so that in the final step I can post it to be saved in the database?
as per my comment I think you are really looking to use a class here, please see the example below to get you started. You may require some research into how OOP (Object Oriented Programming) works though.
public class Meal {
//I dont know what type of data each attribute is supposed to be so I chose ints. Feel free to change.
private int mealId;
private int mealCode;
private int mealType;
public Meal(int mealId, int mealCode, int mealType){
this.mealId = mealId;
this.mealCode = mealCode;
this.mealType = mealType;
}
public int getMealId() {
return mealId;
}
public int getMealCode() {
return mealCode;
}
public int getMealType() {
return mealType;
}
}
Now the Day class:
import java.util.ArrayList;
public class Day {
private ArrayList<Meal> meals = new ArrayList<>();
public Day(Meal...meals){
//This uses magic params to allow you to pass in as many meals as you want.
for(Meal meal : meals){
this.meals.add(meal);
}
}
public ArrayList<Meal> getMeals() {
return meals;
}
}
Now wherever your main method is:
import java.util.ArrayList;
public class Control {
public static void main(String [] args){
ArrayList<Day> days = new ArrayList<>();
//Create your meals.
Meal meal1 = new Meal(1, 1, 1);
Meal meal2 = new Meal(2, 3, 4);
//Add the meals to a day.
Day day1 = new Day(meal1, meal2);
//Add the day to the list of days.
days.add(day1);
//Getting the meal code for the first meal on the first day. This looks complex, but you would likely break it down before getting values.
System.out.println(days.get(0).getMeals().get(0).getMealCode());
}
}

Android Joda Time, Having trouble sorting strings from ISOPeriodFormat

I've been looking everywhere for a solution but can't manage to find one that works.
I have a "Scoreboard" that needs to show the highest "times" (period between two instants) the app has calculated with Joda Time.
All the strings are stocked in an ArrayList and displayed through an ArrayAdapter and a ListView.
The problem : Collections.sort doesn't seem to work properly even with ISO format.
i'm saving the time using the format :
PeriodFormatter formatter = ISOPeriodFormat.standard();
Which gives out this : "PT1M15.664S"
(1 min 15seconds)
That i convert to a string and store into the ArrayList.
How can i sort these strings so it goes from the longest to the shortest amount of time in my Scoreboard ?
I've tried natural sorting and Alphanum Comparator with no luck. Every time it passes a cap (minutes, hours, days) the values get like this :
"PT2.455S"
"PT1.324S"
"PT1M15.333S"
Instead of what i would like :
"PT1M15.333S"
"PT2.455S"
"PT1.324S"
Using Collection.sort(myArrayList) doesn't work either.
Any idea what i should do ?
My code :
// set is a set<String> retrieving it's values from a stringset scores saved
in the sharedpreferences of the app
set = sharedPreferences.getStringSet("scores", null);
//scores is the ArrayList
scores.clear();
if (set != null){
scores.addAll(set);
}else{
scores.add("No Time Yet!");
set = new LinkedHashSet<String>();
set.addAll(scores);
sharedPreferences.edit().putStringSet("scores",set).apply();
}
//removing the String No Time Yet because it no longer serves a purpose here
if ((set != null)&& (set.size()>1)){
scores.remove("No Time Yet!");
}
arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,scores);
listView.setAdapter(arrayAdapter);
Collections.sort(scores);
Thank you for you time.
Short answer: Use the class Duration, not Period.
Explanation:
Your general approach using the class Period is wrong. This type represents a tuple of various amount-unit-pairs. Some of them are not convertible or comparable. For example, it is impossible to determine if P30D is greater or equal to or smaller than P1M (think of February, April or August). So it is pretty clear why you cannot sort by periods resp. why this class does not implement the interface Comparable. And this objection is valid for the objects of type Period as well as for its canonical ISO-representation (as String).
But since you want
the highest "times" (period between two instants)
you can use Duration to determine the absolute amount of elapsed seconds and milliseconds between two given instants. This type is comparable and only has two minor constraints which are probably not important for you:
precision limited to milliseconds
ignores leap seconds
I recommend to compare duration objects, not strings because you want a chronological order, not a lexicographical order. So you could use the String-representation of Duration (like PT72.345S) for storage but parse it for comparison:
Instant i1 = new Instant(0);
Instant i2 = new Instant(72_345);
Duration d1 = new Duration(i1, i2);
Instant i3 = new Instant(60_000);
Instant i4 = new Instant(200_710);
Duration d2 = new Duration(i3, i4);
List<String> scoreTimes = new ArrayList<>();
scoreTimes.add(d1.toString());
scoreTimes.add(d2.toString());
// order from longest times to shortest times
Collections.sort(
scoreTimes,
new Comparator<String>() {
#Override
public int compare(String s1, String s2) {
return Duration.parse(s2).compareTo(Duration.parse(s1));
}
}
);
System.out.println(scoreTimes); // [PT140.710S, PT72.345S]

JFreeChart TimeSeries array exception

this is my first question here ever, and I would appreciate if you can help me.
Since the code I have is way too large to post here, I'll try to describe what my problem is in short.
So, I have made TimeSeries array within my class and array list from where I get values for time series:
private TimeSeries[] seriesArray = new TimeSeries[10];
ArrayList<TempClass> valuesFromArrayList = new ArrayList<>();
I need to make TimeSeries array, because I want to be able to show multiple timeseries graphs. Using only one TimeSeries and addOrUpdate method isn't what I want because then values get mixed when I create more graphs. So, I add values like this:
for(int i = 0; i < valuesFromArrayList.size(); i++)
{
TempClass obj = (TempClass) valuesFromArrayList.get(i);
int timeStamp = obj.getTimeStamp();
int hrsDiff;
int minsDiff;
int secsDiff;
hrsDiff = timeStamp / 3600;
timeStamp = timeStamp - hrsDiff * 3600;
minsDiff = timeStamp / 60;
timeStamp = timeStamp - minsDiff * 60;
secsDiff = timeStamp;
seriesArray[Integer.parseInt(comboBoxValue) - 1].add(new Second(secsDiff, minsDiff, hrsDiff, day, month, year), Math.abs(obj.getValue()));
}
What this part of code does is that it reads values and timestamps from ArrayList I created. There is comboBox where user can choose which timeSeries array index will be in graph. So, if user chooses value 9 from comboBox, timeSeries from index 8 will be chosen and plotted on graph. TimeStamp is simply number of seconds that passed since 00:00:00 at day when values were taken.
TempClass is defined as:
class TempClass
{
private int timeStamp;
private double value;
public TempClass(int a, double b)
{
timeStamp = a;
value = b;
}
public int getTimeStamp()
{
return timeStamp;
}
public double getValue()
{
return value;
}
public void setValue(double val)
{
value = val;
}
}
The problem I have is that when I try to make second (2nd) graph, that is another index of TimeSeries array, I get message:
You are attempting to add an observation for the time period Thu Apr 30 00:00:00 CEST 2015 but the series already contains an observation for that time period. Duplicates are not permitted. Try using the addOrUpdate() method.
I don't want to use addOrUpdate method, I need add method. Values in ArrayList I use to put values into timeSeries are fine, I am 300% sure. I already checked input from comboBox value and it gives correct values.
I have no explanation other that for some reason, even if array index is changed, data I want to write into the series goes to the old series (that is, to the series at the old index). In other words, it seems like even if I change index of array, it keeps writing into the old array index!
It's like equivalent to this (I know this sounds crazy but that is basically what I am getting):
int[] array = new int[5];
array[0] = 1;
array[1] = 2;
System.out.println(array[0]);
And the output I get is
2
This is something I have never heard of before, and I have code similar to this I wrote here in two other places, and in that two places it goes just fine, but in this third place I keep getting that exception.
Is this some kind of bug in JVM?
Does somebody know what this could be?
I don't know too much about TimeSeries, but after skimming the docs about it it says:
"The time series will ensure that (a) all data items have the same
type of period (for example, Day) and (b) that each period appears at
most one time in the series."
Link to Docs
I'm guessing the error is pretty straight forward or a misuse of TimeSeries. It looks like you are simply adding a duplicate date and that the constraints of TimeSeries don't allow that.
You may wish to consider writing a custom class that has the functionality you want. Yet again, I don't know much about TimeSeries, but I hope this helped a little.
Your for loop will always overwrite the value with an index of 0 on seriesArray.
What I mean is, the first time it will write to [0]
The second it will write to [0] then [1]
Is this intended?
I have not looked at the docs too much, but the message says 'the series already contains an observation for that time period.' I think that loop is not doing what you want it to do.

Working with time displayed as strings

Alright so I'm taking an AP Computer Science course and up until now I've found the content easy and unchallenging because I already had a background in Java. However now I have run into an issue with some of the code that the course is providing me with and writing a function based off of it. I've googled it, and tested many different things to try and get it to work and to no avail. So hopefully you guys can shed some light on this and perhaps help me figure it out.
First the book provides me with this code as a basic Time class:
public class Time extends Object {
private int itsHour;
private int itsMin;
/** Create an object for the given hour and minute. If min
* is negative, adjust the values to make 0 <= min < 60. */
public Time (int hour, int min) { // constructor
super();
itsHour = hour;
for (itsMin = min; itsMin < 0; itsMin = itsMin + 60) {
itsHour--;
}
} //=======================
/** Return the time expressed in military time. */
public String toString() {
if (itsHour < 10) {
return ("0" + itsHour) + itsMin;
} else {
return ("" + itsHour) + itsMin;
}
}
/** Return the result of adding this Time to that Time. */
public Time add (Time that) {
// Read below at issue #2
}
}
That was the main class they gave us to work with and then they gave a class called TimeTester which is to be used to execute the commands. The comments dictate what should happen.
import javax.swing.JOptionPane;
class TimeTester {
public static void main (String[] args) {
Time t1 = new Time (13, 25);
Time t2 = new Time (8, -150);
JOptionPane.showMessageDialog (null, "1 " + t1.toString());
JOptionPane.showMessageDialog (null, "2 " + t2.toString());
Time t3 = t1.add (t2);
JOptionPane.showMessageDialog (null, "3 " + t3.toString());
t1 = t2.add (t3);
JOptionPane.showMessageDialog (null, "1 " + t1.toString());
System.exit (0);
} //=======================
}
Now like I said this code was literally handed to me it's making sense of the code and getting it to work for me that I just literally cannot do. So below are basically the key issues I'm running into.
1) I understand how its supposed to run and what the executors do, but I do not understand what exactly its doing to achieve the results.
2) The add function in the first set of code which was basically it's main class is the main part of the assignment. The assignment reads as follows:
Exercise 4.15 (harder) Write the Time method public Time add (Time
that): The executor returns a new Time object that is the sum of the
two, e.g., 0740 add 1430 is
2210. If the sum is more than 2359, drop the extra 24 hours, e.g., 1300 add 1400 is 300.
Assigned from: http://www.cs.ccsu.edu/~jones/chap04.pdf
When I carry over the values to the add function in the TimeTester executing "now.add(wait)" I go to pull that result using "that" but the values don't pull forward.
I've also tried to change up the functions to perhaps get my own understanding and make it work for me. I changed the Time later call in the TimeTester, and then edited the function add to accept 2 values. Then added this code to the add function:
public Time add (Time time1, Time time2) {
String t1String = time1.toString(); // Value is: "0730"
String t2String = time2.toString(); // Value is: "0245"
int t1convert = Integer.parseInt(t1String, 2); // Value is 730
int t2convert = Integer.parseInt(t2String, 2); // Value is: 245
int total = t1convert + t2convert; // Value added together is: 1015
return total; // Return value of total
}
So my call looked like this:
public static void main (String[] args) {
now = new Time (7, 30); // 7:30 in the morning
wait = new Time (2, 45); // 2 hours 45 minutes
later = now.add (now, wait); // produces 10:15 in the morning
JOptionPane.showMessageDialog(null, now + " + " + wait + " = " + later.toString());
System.exit (0);
}
However all that code would not compile and produce a result which could be returned to my TimeTester, it always produced a compile error of "incompatible types" referring to my return total; line. So it obviously cannot return Integers. So I am just absolutely stuck on what to do to make it add the two times.
3) I cannot use the built in Java time functions where it's formatted with semicolons. I know how to do that part which is why this different way is driving me up the wall.
4) I don't want you to write my code for me, I'd like to gain a better understanding of it and perhaps have my mistakes pointed out so that I can comprehend what in the world is going on with it.
I know it's a long post, but when I ask for help I like to be descriptive and provide everything I can because I know it's going to help me better in the long run and hopefully help the person who helps me track down an answer fast.
(PS. All of this is compiled and ran in a program called BlueJ. It's an online course so I have no instructor in class to ask about it all we have is a monitor.)
Consider a method to add two Time instances (a and b) and return a new Time instance; such a method would look like the inverse of the provided Time constructor loop, for (itsMin = min; itsMin < 0; itsMin = itsMin + 60), specifically - it should increment some hours count (perhaps by adding the hours from a and b) while the number of minutes is > 59 and subtracting 60 minutes at a time... This method might look something like this
public static Time add(Time a, Time b) { // Add two Time(s) together.
if (a == null) { // if a is null, just return b.
return b;
} else if (b == null) { // if b is null, just return a.
return a;
}
int hours = a.itsHour + b.itsHour; // Add the hours together.
int minutes = a.itsMin + b.itsMin; // Add the minutes together.
for (; minutes > 59; minutes -= 60) { // Increment hours as necessary, while
// decrementing the minute count by 60.
hours++;
}
return new Time(hours, minutes); // Return the new Time instance.
}
public static void main(String[] args) {
Time now = new Time(7, 30); // 7:30 in the morning
Time wait = new Time(2, 45); // 2 hours 45 minutes
Time later = Time.add(now, wait); // produces 10:15 in
// the morning
System.out.println(later);
}
Outputs
1015
The compiler is complaining that you are returning an int, when you defined the function return type to be "Time":
public Time add (Time time1, Time time2) {
String t1String = time1.toString(); // Value is: "0730"
String t2String = time2.toString(); // Value is: "0245"
int t1convert = Integer.parseInt(t1String, 2); // Value is 730
int t2convert = Integer.parseInt(t2String, 2); // Value is: 245
int total = t1convert + t2convert; // Value added together is: 1015
return total; // Return value of total
}
The return type is Time:
public Time add (Time time1, Time time2) ...
You return "total", which is of type "int":
int total = t1convert + t2convert;
return total; …
What you would need to do is to make a new Time object which has the answer stored inside of it. For example:
Time t3 = new Time(0, total); // This is assuming that "total" represents the minutes
Regarding the issue in the comment,
#Mike'Pomax'Kamermans Looking at your comment i managed to write this
line of code to see if i could execute it that way and I cannot. "Time
t1 = new Time(this.hour, that.hour); " spits out "cannot find symbol -
variable hour". Any insight into this? – user1686765 3 mins ago
"this.hour" is looking at the current Time instance, which is a instance of the Time class, for a member variable called "hour." If you go to your Time class, you will see that it only has some methods and 2 variables called "itsHour" and "itsMin". So it cannot find the variable "hour" because it does not exist. I think you meant to put "this.itsHour" in place of "this.hour".

Categories

Resources