Answered step by step
Verified Expert Solution
Question
1 Approved Answer
(READ INSTRUCTIONS CAREFULLY) _____________________________________________________________________________________________________________________________ Person.java: import java.util.Comparator; /** * A class representing a person and their birth date. * * @author Mark Young (A00000000) */
(READ INSTRUCTIONS CAREFULLY)
_____________________________________________________________________________________________________________________________
Person.java:
import java.util.Comparator; /** * A class representing a person and their birth date. * * @author Mark Young (A00000000) */ public class Person implements Comparable{ // ---------- instance variables ---------- // private String name; private final Date birthDate; // ---------- constructors ---------- // /** * Build a Person with the given name and birth date. * * @param rName the Person's name * @param rBirthDate the Person's birth date */ public Person(String rName, Date rBirthDate) { name = rName; birthDate = rBirthDate; } /** * Build a Person with the given name and the String representation of their * birth date. * * @param rName the Person's name * @param rDateString the Person's birth date as a String * @throws IllegalDateException if the String given does not correspond to a * valid date in the Gregorian calendar */ public Person(String rName, String rDateString) { this(rName, Date.parseDate(rDateString)); } // ---------- getters ---------- // /** * Get this Person's name. * * @return this Person's name */ public String getName() { return name; } /** * Get this Person's birth date. * * @return this Person's birth date */ public Date getBirthDate() { return birthDate; } // ---------- setters ---------- // /** * Change this Person's name. * * @param newName the new name for this Person */ public void setName(String newName) { name = newName; } // ---------- Comparable implementation ---------- // /** * Compare this Person to that Person, sorting them by name. * * @param that the other Person * @return an int value representing whether this Person should be first (a * negative number), that Person (a positive number), or that it doesn't * matter (zero) */ @Override public int compareTo(Person that) { return this.name.compareTo(that.name); } // ---------- Comparators ---------- // /** * Compare people by their age, oldest to youngest. */ public static Comparator BY_AGE = (one, other) -> one.birthDate.compareTo(other.birthDate); /** * Compare people by their birth date, from earliest in the year to latest. */ public static Comparator By_BIRTHDATE = (one, other) -> Date.WITHIN_YEAR.compare(one.birthDate, other.birthDate); // ---------- static methods ---------- // /** * Get the author information for this class. * * @return the author's name and A-number in the CSCI 2341 format */ public static String getAuthor() { return "Mark Young (A00000000)"; } }
_______________________________________________________________________________________________________________________________
SortingPeople.java:
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; import java.util.Scanner; /** * Generate a list of people and sort it in multiple ways. * * @author Mark Young (A00000000) */ public class SortingPeople { /** * @param args the command line arguments */ public static void main(String[] args) { printIntroduction(); pause(); Listpeople = generatePeople(); // create and show original list System.out.println("Here are the people: "); showList(people); pause(); // sort by name Collections.sort(people); System.out.println("Here they are sorted by name: "); showList(people); pause(); // sort by age System.out.println("Here they are sorted by age: "); Collections.sort(people, Person.BY_AGE); showList(people); pause(); // sort by birthday System.out.println("Here they are sorted by birthday: "); Collections.sort(people, Person.By_BIRTHDATE); showList(people); } /** * Print the introduction for this program, including author information. */ private static void printIntroduction() { System.out.println("" + "Basics for Sorting " + "------------------ " + "This program generates a list of people " + "then sorts them in three ways. " + "Program by: " + SortingPeople.getAuthor() + " " + "Person class by: " + Person.getAuthor() + " " + "Date class by: " + Date.getAuthor() + " " + "IllegalDateException class by: " + IllegalDateException.getAuthor()); } /** * Generate a list of people. The people are generated randomly. * * @return a list of people. */ private static List generatePeople() { List result = new ArrayList(); int numPeople = 10; for (int i = 0; i people) { for (Person person : people) { System.out.println(" - " + person.getName() + " (born " + person.getBirthDate() + ")"); } } /** * Prompt the user and wait for them to press the enter key. */ private static void pause() { System.out.print(" ...press enter..."); KBD.nextLine(); System.out.println(); } /** * Get the author information for this class. * * @return the author's name and A-number in the CSCI 2341 format */ public static String getAuthor() { return "Mark Young (A00000000)"; } /** * Generate a random person. Random name and birth date. * * @return a person with randomly generated name and birth date. */ private static Person randomPerson() { try { return new Person(randomName(), new Date(randomYear(), randomMonth(), randomDay())); } catch (IllegalArgumentException iae) { return new Person("Mark", "1962-01-20"); } } /** * Pick a name at random from a list. * * @return a randomly chosen name. */ private static String randomName() { return randomOf("Alex", "Bina", "Carl", "Djen", "Egan", "Fred", "Gita", "Hiro", "Inga", "Jack", "Kate", "Lien", "Maya", "Neva", "Opal", "Piet", "Quin", "Raul", "Soni", "Taya", "Udea", "Vala", "Wiek", "Xavi", "Yuli", "Zoey"); } /** * Pick a random year from 1900 on. * * @return a random year in the range [1900-2020). */ private static int randomYear() { return 1900 + myRandom.nextInt(120); } /** * Pick a month at random. * * @return a random month (1..12). */ private static int randomMonth() { return 1 + myRandom.nextInt(12); } /** * Pick a date within a month at random. NOTE: may not be in the range for a * shorter month (Feb, Apr, Jun, Sep, Nov). * * @return a random date within a month (1..31). */ private static int randomDay() { return 1 + myRandom.nextInt(31); } /** * Pick one of the given values at random. * * @param the type of elements given. * @param values the values given. * @return one of those values, chosen at (pseudo-)random. */ private static T randomOf(T... values) { int len = values.length; int choice = myRandom.nextInt(len); return values[choice]; } // For pauses private static final Scanner KBD = new Scanner(System.in); // random number generator private static final Random myRandom = new Random(); }
_______________________________________________________________________________________________________________________________
TestDate.java:
/** * A program to test some of the methods in Date that were not tested in the * sample driver program. * * NOTE: there are STILL MORE tests you could do! * * @author Mark Young (A00000000) */ public class TestDate { /** * @param args the command line arguments */ public static void main(String[] args) { // valid date tryDate(2023, 3, 8, "2023-03-08"); // invalid year tryDate(-1, 10, 10); // invalid months tryDate(2023, 0, 20); tryDate(2023, 13, 10); // invalid days tryDate(2023, 1, 0); tryDate(2023, 3, 32); // leap years tryDate(2020, 2, 29, "2020-02-29"); tryDate(2016, 2, 29, "2016-02-29"); tryDate(1972, 2, 29, "1972-02-29"); tryDate(1600, 2, 29, "1600-02-29"); tryDate(2000, 2, 29, "2000-02-29"); tryDate(3200, 2, 29, "3200-02-29"); tryDate(2023, 2, 29); tryDate(2019, 2, 29); tryDate(1993, 2, 29); tryDate(1900, 2, 29); tryDate(2100, 2, 29); tryDate(2300, 2, 29); // month lengths tryDate(2023, 1, 31, "2023-01-31"); tryDate(2023, 3, 31, "2023-03-31"); tryDate(2023, 4, 30, "2023-04-30"); tryDate(2023, 4, 31); tryDate(2023, 5, 31, "2023-05-31"); tryDate(2023, 6, 30, "2023-06-30"); tryDate(2023, 6, 31); tryDate(2023, 7, 31, "2023-07-31"); tryDate(2023, 8, 31, "2023-08-31"); tryDate(2023, 9, 30, "2023-09-30"); tryDate(2023, 9, 31); tryDate(2023, 10, 31, "2023-10-31"); tryDate(2023, 11, 30, "2023-11-30"); tryDate(2023, 11, 31); tryDate(2023, 12, 31, "2023-12-31"); // parsing illegal dates tryDate("2023-02-29"); tryDate("3/8/23"); tryDate("Wednesday, March 3rd"); } /** * Try to create an invalid date. * * @param year the (possibly invalid) year * @param month the (possibly invalid) month * @param day the (possibly invalid) day */ private static void tryDate(int year, int month, int day) { try { Date myDate = new Date(year, month, day); System.out.println("Created the illegal date " + myDate); } catch (IllegalDateException ide) { // Cool! } catch (Exception e) { System.out.println("Threw the wrong exception for " + String.format("(%d, %d, %d)", year, month, day)); System.out.println(e); } } /** * Try to create a valid date. * * @param year the year * @param month the month * @param day the day * @param result the expected String representation of the date */ private static void tryDate(int year, int month, int day, String result) { try { Date myDate = new Date(year, month, day); String got = myDate.toString(); if (!result.equals(got)) { System.out.println("Wrong format for " + result + ": got " + got); } } catch (IllegalDateException ide) { System.out.println("Threw an IDE for " + String.format("(%d, %d, %d)", year, month, day)); System.out.println(ide); } catch (Exception e) { System.out.println("Threw the wrong exception for " + String.format("(%d, %d, %d)", year, month, day)); System.out.println(e); } } /** * Try to parse an invalid date. * * @param whatever a String representation of an invalid date */ private static void tryDate(String whatever) { try { Date myDate = Date.parseDate(whatever); System.out.println("Parsed the illegal date " + whatever); } catch (IllegalDateException ide) { // Cool! } catch (Exception e) { System.out.println("Threw the wrong exception for " + whatever); System.out.println(e); } } }Due Date: Wednesday, March 8 File(s) to be submitted: Date.java, IllegalDateException.java Sample Output: SampleOutput.html Starter Files: - Person.avava - Sortingpeople.java - TestDate.java SUBMIT/Check Sorting People (practice with data type classes, exceptions and interfaces) Summary I have provided you with a program SortingPeople that generates a list of people then sorts it in three ways. I have also provided you with a program called TestClass that does some further testing on the Date class. If your class is correct, it should produce NO OUTPUT! I have also provided you with the Person class. Each person has a name and a birth date. People naturally sort by name, but may also be sorted by age and by birthday. You need to create the Date class. The date class has a year (any positive integer), month ( 1 to 12 ), and a day (1..28, 29, 30, or 31, depending on the month and year). It is immutable (meaning that it can't be changed after it's created). You also need to create an IllegalDateException class. It gets thrown by the Date class when someone tries to create an invalid date. Every one of those classes also has a static getAuthor () method that returns your author information in the form "name (A-mumber)". You must build your Date class "from scratch". You are not allowed to use any of the various date classes from any of the various Java packages that define such things. Details Tou have two classes to create this time. One of them is a data type and the other is an exception. They must work together with the Person data type so hat the SortingPeople program runs without crashing and produces correct output. The Date class needs to be sortable, both naturally, and within a year. You should use the Person class as an example of how to do that. To give a class a natural order, it needs to implement the Comparable interface (where the name of the class replaces the ...). For example, Person mplements Comparable . To implement Comparable the class needs to define the compareTo(... that) method (where the name of the class replaces the ...). Thus Person defines ompareTo(Person that). Note the following lines: public class Person implements comparable Person >{ public int compareTo(Person that) \{ return this.name.compareTo(that.name) says that to compare this Person to that Person, you have this Person's name compare itself to that Person's name. Note that that is using the natural order for Strings by calling the compareTo method declared in the String class. o give a class another way to sort, you need to give it a Comparator (where the ... is, once again, replaced by the class name). Comparators are sually defined using a lambda expression, giving the items to compare. For example, Person defines two more ways to compare people. BY AGE ompares two people by their birth dates: public static Comparator> BY AGE = (one, other) one.birthDate.compareTo(other.birthDate); says to compare two people by age, ask one's birth date to compare itself to the other's birth date. Note that that is using the natural order for Dates by calling the compareTo method declared in the Date class. The Person class also gives a Comparator that allows people to be sorted by their birth date within the year. (So people born in January come before eople born in February, regardless of which year they were born in.) BY_BIRTHDATE allows this comparison: \( \begin{array}{l} \text { public static Comparator By_BIRTHDATE } \\ =\text { (one, other) } \\ \text { Date.WITHIN_YEAR.compare(one.birthDate, other.birthDate); }\end{array} \) Note that this one is using a Comparator defined in the Date class: WITHIN_YEAR. It says that to compare one Person with another Person by their birth dates, you need to compare their birth dates using Date's WITHIN_YEAR Comparator. Comparators define the compare method, and so that is the method that needs to be called here. Recall that a lambda expression can be used when an interface has only one method to declare -- as is the case with a Comparator and its compare method. Don't get Comparable and Comparator confused. Don't get compareTo and compare confused. he Date Class The Date class has a year, a month, and a day. These numbers are assigned by the constructor and cannot be changed once set. The Date class has a tostring method that presents the Date in the international standard format: YYYY-MM-DD -- year, month and day. For example, the ue date for this assignment is Wednesday, March 8th, 2023 -- 2023-03-08. The year is four digits (with leading zeroes if necessary), and the month and ay are two digits (again with leading zeroes if necessary). If you don't know it already, you should really learn the formatting language used by System.out.printf and String. format. It makes your The year, month and day must mark out a valid date in the Gregorian calendar. (That is the calendar we use in Canada, and, indeed, in most of the world.) The restrictions are: - the year must be greater than 0. - the month must be 1 to 12 . - the day must be 1 to the number of days in the Date's month. Your Date constructor must take the three numbers in the year-month-day order. It must throw an IllegalDateException if the requested date is invalid. You need to create that exception class. (See below.) Dates sort naturally from earliest to latest. That is, if two dates have different years, then the one with the smaller year comes first. Otherwise, if they have different months, then the one with the smaller month comes first. And otherwise, the one with the smaller day comes first. Note that Integer is a Comparator . This is, it has a compare method that will return an appropriate value when comparing two integers. For example, Integer.compare(25,40) will return a value that indicates that 25 should come before 40 . You'll need to use that to compare the years/months/days, since int doesn't have a compareto method. (And yes, you can use ints where the code is expecting Integers.) Your Date class also needs to provide the WITHIN_YEAR Comparator used by the Person class. If two dates have different months, then the one with the Your Date class also needs to provide the WITHIN_YEAR Comparator used by the Person class. If two dates have different months, then the one with the smaller month comes first. Otherwise, the one with the smaller day comes first. The Date class has some helpful methods: - isLeapYear (int year) checks whether its argument is a leap year. The leap years in the Gregorian calendar are those divisible by 4 (unless divisible by 100), and those divisible by 400 . Example leap years are 2020, 2016, and 1972 (all divisible by 4 but not 100); and 1600, 2000, and 3200 (all divisible by 400 ). Example non-leap years are 2023, 2019, and 1993 (none divisible by 4); and 1900,2100, 2300 (none divisible by 400). - daysInMonth(int month, int year) returns how many days are in the given month. For February (month 2), the number of days depends on whether year is a leap year. In leap years February has 29 days; in non-leap years it has 28 Months April (4), June (6), September (9), and November (11) all have 30 days. Every other month has 31 days. - isvalid(int year, int month, int day) checks whether the given (supposed) date is valid. That is, whether the year is greater than zero, the month is 1 to 12 , and the day is the number of a day in that month and year. It returns true if the date is valid, and false otherwise. - parseDate(String datestr) which tries to read a valid date out of the given String. The datestr should be a String in the same format as the tostring method provides: YYYY-MM-DD. Your class does not have to parse any other kind of date. In particular, it has no need to parse dates in the form 3/8/23 or 8/03/23 or any other format. To read a date out of such a String is pretty easy. You replace all its hyphens with spaces (so "2023-03-08" becomes "2023 03 08") then read in th numbers using a Scanner on that String. Hint: there is a String method called replaceAll. Of course, the fact that datestr should have a proper date in it is no guarantee that it will. datestr might have an invalid date in it, such as "202302-29" or "3/8/23" or "Wednesday, March 3rd". In that case, parseDate should throw an IllegalDateException. The easiest way to deal with such problems is to let the Scanner or constructor throw the exception. If it's the wrong kind of exception, then have parseDate catch it and throw one of the correct type. ake sure you use all the correct modifiers on your methods. Some methods should be static, and others must not be. Be sure your get them the right wa pund. e IllegalDateException class his class should extend RuntimeException so that we don't need to add a throws clause to the method throwing it. exception, then have parseDate catch it and throw one of the correct type. Make sure you use all the correct modifiers on your methods. Some methods should be static, and others must not be. Be sure your get them the right way 'round. The IllegaldateException class This class should extend RuntimeException so that we don't need to add a throws clause to the method throwing it. The class should have two constructors: - IllegalDateException(String message), which sets this exception's message property. The message property is inherited! You set it using the corresponding constructor of the superclass. - IllegalDateException(), which leaves the message as nu11 (no message). The message for your IllegalDateException should be the bad data that caused the exception to be thrown. In parseDate that'd be the datestr. In the constructor, it'd be the illegal date (in YYYY-MM-DD format). You might want to make a private method to format a Date so you can call it from the constructor as well as from tostring. Due Date: Wednesday, March 8 File(s) to be submitted: Date.java, IllegalDateException.java Sample Output: SampleOutput.html Starter Files: - Person.avava - Sortingpeople.java - TestDate.java SUBMIT/Check Sorting People (practice with data type classes, exceptions and interfaces) Summary I have provided you with a program SortingPeople that generates a list of people then sorts it in three ways. I have also provided you with a program called TestClass that does some further testing on the Date class. If your class is correct, it should produce NO OUTPUT! I have also provided you with the Person class. Each person has a name and a birth date. People naturally sort by name, but may also be sorted by age and by birthday. You need to create the Date class. The date class has a year (any positive integer), month ( 1 to 12 ), and a day (1..28, 29, 30, or 31, depending on the month and year). It is immutable (meaning that it can't be changed after it's created). You also need to create an IllegalDateException class. It gets thrown by the Date class when someone tries to create an invalid date. Every one of those classes also has a static getAuthor () method that returns your author information in the form "name (A-mumber)". You must build your Date class "from scratch". You are not allowed to use any of the various date classes from any of the various Java packages that define such things. Details Tou have two classes to create this time. One of them is a data type and the other is an exception. They must work together with the Person data type so hat the SortingPeople program runs without crashing and produces correct output. The Date class needs to be sortable, both naturally, and within a year. You should use the Person class as an example of how to do that. To give a class a natural order, it needs to implement the Comparable interface (where the name of the class replaces the ...). For example, Person mplements Comparable . To implement Comparable the class needs to define the compareTo(... that) method (where the name of the class replaces the ...). Thus Person defines ompareTo(Person that). Note the following lines: public class Person implements comparable Person >{ public int compareTo(Person that) \{ return this.name.compareTo(that.name) says that to compare this Person to that Person, you have this Person's name compare itself to that Person's name. Note that that is using the natural order for Strings by calling the compareTo method declared in the String class. o give a class another way to sort, you need to give it a Comparator (where the ... is, once again, replaced by the class name). Comparators are sually defined using a lambda expression, giving the items to compare. For example, Person defines two more ways to compare people. BY AGE ompares two people by their birth dates: public static Comparator> BY AGE = (one, other) one.birthDate.compareTo(other.birthDate); says to compare two people by age, ask one's birth date to compare itself to the other's birth date. Note that that is using the natural order for Dates by calling the compareTo method declared in the Date class. The Person class also gives a Comparator that allows people to be sorted by their birth date within the year. (So people born in January come before eople born in February, regardless of which year they were born in.) BY_BIRTHDATE allows this comparison: \( \begin{array}{l} \text { public static Comparator By_BIRTHDATE } \\ =\text { (one, other) } \\ \text { Date.WITHIN_YEAR.compare(one.birthDate, other.birthDate); }\end{array} \) Note that this one is using a Comparator defined in the Date class: WITHIN_YEAR. It says that to compare one Person with another Person by their birth dates, you need to compare their birth dates using Date's WITHIN_YEAR Comparator. Comparators define the compare method, and so that is the method that needs to be called here. Recall that a lambda expression can be used when an interface has only one method to declare -- as is the case with a Comparator and its compare method. Don't get Comparable and Comparator confused. Don't get compareTo and compare confused. he Date Class The Date class has a year, a month, and a day. These numbers are assigned by the constructor and cannot be changed once set. The Date class has a tostring method that presents the Date in the international standard format: YYYY-MM-DD -- year, month and day. For example, the ue date for this assignment is Wednesday, March 8th, 2023 -- 2023-03-08. The year is four digits (with leading zeroes if necessary), and the month and ay are two digits (again with leading zeroes if necessary). If you don't know it already, you should really learn the formatting language used by System.out.printf and String. format. It makes your The year, month and day must mark out a valid date in the Gregorian calendar. (That is the calendar we use in Canada, and, indeed, in most of the world.) The restrictions are: - the year must be greater than 0. - the month must be 1 to 12 . - the day must be 1 to the number of days in the Date's month. Your Date constructor must take the three numbers in the year-month-day order. It must throw an IllegalDateException if the requested date is invalid. You need to create that exception class. (See below.) Dates sort naturally from earliest to latest. That is, if two dates have different years, then the one with the smaller year comes first. Otherwise, if they have different months, then the one with the smaller month comes first. And otherwise, the one with the smaller day comes first. Note that Integer is a Comparator . This is, it has a compare method that will return an appropriate value when comparing two integers. For example, Integer.compare(25,40) will return a value that indicates that 25 should come before 40 . You'll need to use that to compare the years/months/days, since int doesn't have a compareto method. (And yes, you can use ints where the code is expecting Integers.) Your Date class also needs to provide the WITHIN_YEAR Comparator used by the Person class. If two dates have different months, then the one with the Your Date class also needs to provide the WITHIN_YEAR Comparator used by the Person class. If two dates have different months, then the one with the smaller month comes first. Otherwise, the one with the smaller day comes first. The Date class has some helpful methods: - isLeapYear (int year) checks whether its argument is a leap year. The leap years in the Gregorian calendar are those divisible by 4 (unless divisible by 100), and those divisible by 400 . Example leap years are 2020, 2016, and 1972 (all divisible by 4 but not 100); and 1600, 2000, and 3200 (all divisible by 400 ). Example non-leap years are 2023, 2019, and 1993 (none divisible by 4); and 1900,2100, 2300 (none divisible by 400). - daysInMonth(int month, int year) returns how many days are in the given month. For February (month 2), the number of days depends on whether year is a leap year. In leap years February has 29 days; in non-leap years it has 28 Months April (4), June (6), September (9), and November (11) all have 30 days. Every other month has 31 days. - isvalid(int year, int month, int day) checks whether the given (supposed) date is valid. That is, whether the year is greater than zero, the month is 1 to 12 , and the day is the number of a day in that month and year. It returns true if the date is valid, and false otherwise. - parseDate(String datestr) which tries to read a valid date out of the given String. The datestr should be a String in the same format as the tostring method provides: YYYY-MM-DD. Your class does not have to parse any other kind of date. In particular, it has no need to parse dates in the form 3/8/23 or 8/03/23 or any other format. To read a date out of such a String is pretty easy. You replace all its hyphens with spaces (so "2023-03-08" becomes "2023 03 08") then read in th numbers using a Scanner on that String. Hint: there is a String method called replaceAll. Of course, the fact that datestr should have a proper date in it is no guarantee that it will. datestr might have an invalid date in it, such as "202302-29" or "3/8/23" or "Wednesday, March 3rd". In that case, parseDate should throw an IllegalDateException. The easiest way to deal with such problems is to let the Scanner or constructor throw the exception. If it's the wrong kind of exception, then have parseDate catch it and throw one of the correct type. ake sure you use all the correct modifiers on your methods. Some methods should be static, and others must not be. Be sure your get them the right wa pund. e IllegalDateException class his class should extend RuntimeException so that we don't need to add a throws clause to the method throwing it. exception, then have parseDate catch it and throw one of the correct type. Make sure you use all the correct modifiers on your methods. Some methods should be static, and others must not be. Be sure your get them the right way 'round. The IllegaldateException class This class should extend RuntimeException so that we don't need to add a throws clause to the method throwing it. The class should have two constructors: - IllegalDateException(String message), which sets this exception's message property. The message property is inherited! You set it using the corresponding constructor of the superclass. - IllegalDateException(), which leaves the message as nu11 (no message). The message for your IllegalDateException should be the bad data that caused the exception to be thrown. In parseDate that'd be the datestr. In the constructor, it'd be the illegal date (in YYYY-MM-DD format). You might want to make a private method to format a Date so you can call it from the constructor as well as from tostring
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started