I'm trying to write a getter which takes specific data from an enum and returns a double, which I will use later in my code and I'm not sure how to go about it. This is what I've come up with so far:
//This getter takes the enum of Month and converts it so it returns the mean precipitation of a certain month
public double getPrecipitationMonth(Month month){
//more in here
return this.precipitationMonths[month.ordinal()];
The enum in question is the months of the year ie {JANUARY, FEBRUARY...} and the data for each month is in a separate file.
I'm new to programming - hope you can help! Thank you
I think your general idea is very sound. But I'd just use a Map like so:
Map<Month,Double> data = new HashMap<>;
for(Row row : readFromFile()){
data.put(row.getMonth(), row.getData());
}
So that it's more obvious.
You can use a HashMap for this, assigning enum values as keys
enum Month {
// Your enum
}
HashMap< Month, Double > monthPrecipitation = new HashMap< Month, Integer >();
public double getPrecipitationMonth( Month month ) {
return monthPrecipitation.get( month );
}
I would write eum something like that:
public enum Month {
JAN (1.0),
FEB (2.0),
MAR (3.0);
private double mId;
public static Month fromDoubleToEnum( double value ) throws Exception{
for ( Month c : Month.values() ) {
if ( c.mId == value ) {
return c;
}
}
throw new Exception( "Illegal Month value: " + value );
}
public double fromEnumToDouble(){
return mId;
}
private EModule (double num){
mId = num;
}
}
Here we have method: fromEnumToDouble that returns double on enum.
Test
public static void main(String[] args) {
Month mod = Month.FEB;
double toDouble = mod.fromEnumToDouble();
System.out.println(toDouble); // out 2.0
}
Use an EnumMap to store your precipitationMonths array instead.
EnumMap<Month,Something> precipitationMonths = new EnumMap<Month,Something>(Month.class);
precipitationMonths.put(Month.JANUARY, someValue); // Add a value
Something someValue = precipitationMonths.get(Month.JANUARY); // Get a value
Regarding that your data are located in file you need to create a class that will store that data and be able to map them.
The Java has really poor support for calendar, but you can work with it using Calendar class
You can create a enum for calendar but it is not mandatory.
enum Month{
JANUARY(Calender.JANUARY);
private final int month;
Month(int month) {
this.month = month;
}
public int month() {
return month;
}
}
When you solve the first problem of matching the data from file with months.
private final Map<Month,Double> precipitationMap = new EnumMap<>();
private void assignPrecipitation(Month month, double precipitation) {
this.precipitationMap.put(month,precipitation);
}
public double getPrecipitation(Month month) {
if(this.precipitationMap.contains(month) {
return this.precipitationMap.get(month).doubleValue();
}
throw new IllegalStateException("The Precipitation was not found for: " + myCalendar);
}
Related
I need to compare the attribute "date" of objects included in an ArrayList.
The objects included in the ArrayList are of type "Books" and each Book has a launching date.
The date is given in a String format.
public ArrayList<Book> group;
What I have done is :
public static Comparator<Book> ComparaisonDate = new Comparator<Book>() {
SimpleDateFormat data = new SimpleDateFormat("dd/mm/yyyy");
#Override
public int compare(Book l1, Book l2) {
try {
return data.parse(l1.launchingDate).compareTo(data.parse(l2.launchingDate));
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
};
public void sort(int option) {
Collections.sort(this.group, Book.ComparaisonDate);
}
When I add two books with the dates: 01/08/2020 and 12/05/2020 the result of the sort() function is:
01/08/2020
12/05/2020
The result should be: 12/05/2020 and then 01/05/2020.From what I can see, it compares only the day and not the month or year. Do you have any idea how to fix this? thanks
mm in the pattern stands for Minutes of the Hour, therefore the sorting is actually correct. You need MM. See https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html for valid patterns.
Here follow two pieces of code, and I know that it's not working as intended.
The Date instance is not supposed to be able to change after it's created, but because the getDate method returns an array(reference), it's able to change in the second part of my provided code with int[] dateValue = date.getDate ();.
I think I'm overthinking this a bit, and need a fresh pair of eyes on the problem.
Am I just supposed to build the Date-class with int y, int m, int d instead of int[] ymd or can I modify the return method and/or add a few more methods to either Date or Problem2?
Any ideas for how to fix this in the best or easiest way? The class Problem2 should print out the same thing both times, and/or the Date-instance should NOT be changeable!
As for now, I don't even know in what direction I should be thinking.
public class Date
{
private int[] ymd = new int[3];
public Date (int year, int month, int day)
{
ymd[0] = year;
ymd[1] = month;
ymd[2] = day;
}
public int[] getDate ()
{
return ymd;
}
public void printDate ()
{
System.out.println (ymd[0] + "-" + ymd[1] + "-" + ymd[2]);
}
}
public class Problem2
{
public static void main (String[] args)
{
Date date = new Date (2019, 6, 15);
date.printDate ();
int[] dateValue = date.getDate ();
dateValue[2] = 38;
date.printDate ();
}
}
As for now, Problem2 prints out:
2019-6-15
2019-6-38
When "fixed", it should print the same date both times.
To make the object immutable, you should return a copy of the array in the getDate() method.
To do this, you can replace the method by:
public int[] getDate ()
{
return Arrays.copyOf(ymd, ymd.length);
}
Arrays.copyOf take the array and his length as parameter. The it returns a copy of the array.
Supposing that I have a list of Test as below:
public class Test {
public static enum Unit {
DAY, WEEK, MONTH, YEAR /* , DAY_TO_DAY */
}
private int value;
private Unit unit;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Unit getUnit() {
return unit;
}
public void setUnit(Unit unit) {
this.unit = unit;
}
}
I will have a list of Test with the below values :
3 day,
5 month,
5 day,
6 year,
6 week,
12 week,
and our expection result as below :
3 day, 5 day, 6 week , 12 week, 5 month, 6 year
Currently, I create a code as below
Collections.sort(tests, new Comparator<Test >() {
#Override
public int compare(Test o1, Test o2) {
if(o1.getValue() > o2.getValue()) return 1;
if(o1.getValue() < o2.getValue()) return -1;
return 0;
}
However, it only sort by value and not by Unit.
The result with the above implementation is :
3 day, 5 day, 5 month, 6 week , 6 year, 12 week.
Please tell me know the way to satisfy two conditions (Unit and values) in this case.
Thanks.
You'll need to convert first into common format, and then compare. Since days are your smallest type, you should convert the two instances you're comparing into a number of days, and then compare based on that.
But you have some disambiguation to do first. How long is a month? Is it longer than 30 days, or shorter, or the same?
If you simply want to compare according to your example the following code solves the problem:
Collections.sort(terms, new Comparator<Test>() {
#Override
public int compare(final Test o1, final Test o2) {
int unitCompare = o1.getUnit().compareTo(o2.getUnit());
if (unitCompare == 0) {
return o1.getValue() - o2.getValue();
}
return unitCompare;
}
});
However, this code does NOT factor in that months can have different length and the code does NOT factor in that 35 days is longer than a month.
In order to do that i suggest that the classes from the java.time package (such as java.time.Period) are used to make proper comparisons (a good trail to learn about this can be found here). If Java 8 is not an option Joda Time provides the same type of functionality.
You'll first have to check on the basis of Unit and then on the basis of Value in the overridden compareTo(). See here the implementation of sorting on the basis of lastname and then firstname:http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
Use TimeUnit to replace your Unit enum.
Your Term class could therefore have a .toMillis() method which is very simple:
public final long toMillis()
{
return timeUnit.toMillis(value);
}
You can then just Long.compare(o1.toMillis(), o2.toMillis()) in your Comparator.
Other solutions:
if you use Java 8, use the new date/time API;
if you use Java 7- and threetenbp, use the same methods, backported;
if you use Java 7- and Joda Time, use Period. It is nearly equivalent to that of Java 8's/threetenbp's.
If you really want to do it that way, assign your enums values like so:
DAY(1), WEEK(7), MONTH(31), YEAR(365)
than multiply in your comperator
Unit.getValue() * value
e.g. 4 MONTH gives you 31 * 4 = 124 is bigger than 100 DAY.
still you have the problem that teher are months with less than 31 days. recommend to convert to some common date units e.g. joda time.
Please use the compareto function as below:
public int compareTo(Object o) {
Test t1 = (Test)this;
Test t2 = (Test)o;
if(t1.getValue()*(t1.getUnit().getValue()+1) > t2.getValue()*(t2.getUnit().getValue()+1)) return 1;
if(t1.getValue()*(t1.getUnit().getValue()+1) < t2.getValue()*(t2.getUnit().getValue()+1)) return -1;
return 0;
}
and change the enum to
public static enum Unit {
DAY(1), WEEK(7), MONTH(31), YEAR(365) ;/* , DAY_TO_DAY */
private final int id;
Unit(int id) { this.id = id; }
public int getValue() { return id; }
}
Now you use the collection.sort(), and it will be sorted automatically
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.
I'm playing around with arrays and enums and i was wondering whats the most effect way to create a Comparator class to sort these dates in descending order. Heres my code.
public enum Month {JAN(1), FEB(2), MAR(3), APR(4), MAY(5), JUN(6), JUL(7),
AUG(8), SEPT(9), OCT(10), NOV(11), DEC(12);
final int monthBoundary;
Month(int y){
monthBoundary=y;}
}
public enum Date {FIRST(1), SECOND(2), THIRD(3), FORTH(4),
FIFTH(5)... THIRTYFIRST(31);
final int dateBoundary;
Date(int z){
dateBoundary=z;}
}
//constructor etc here
private static final List<Cal> calendar = new ArrayList<Cal>();
static {
for (Month month : Month.values()) {
for (Date date : Date.values()) {
calendar.add(new Cal(date, month));
}
}
}
//creates new calendar dates
public static ArrayList<Cal> newCal() {
return new ArrayList<Cal>(calendar);
}
Using the following statement i can print the array in the order its created.
System.out.print(Card.calendar());
How do you create a Comparator class to sort these dates in descending order?
Ideally i would like it to sort the array whether it was already in order or in a random order.
At this stage i am not concerned about dates that do not exist (e.g. Feb 31st) as i'm merely practising and self studying... Just trying to get the concept :)
Thanks.
ADDED:
public ArrayList<Cal> sortDescending(ArrayList<Cal> calList){
Comparator<Cal> c = Collections.reverseOrder();
Collections.sort(calList, c);
return calList;
}
Collections.sort(list, new Comparator<Cal>() {
#Override
public int compare(Cal cal1, Cal cal2) {
int result = -cal1.getMonth().compareTo(cal2.getMonth()));
if (result == 0) {
result = -cal1.getDate().compareTo(cal2.getDate()));
}
return result;
}
});