//DatesHashsetTest.java //create random Dates and add to hash set. //Date and IncDate are in this file for a standalone demo program. //How are duplicates determined? Date must override equals() and hashCode() import java.util.*; import javax.swing.*; public class DatesHashSetTest { public static void main(String[] args) { String input; int size; HashSet myDatesHashSet = new HashSet(); input = JOptionPane.showInputDialog( "Enter number of random dates" ); size = Integer.parseInt( input ); Date randDate; for (int i=1; i<=size; i++) { randDate = generateRandomDate(); System.out.print(randDate); if (myDatesHashSet.add(randDate)) System.out.println(" Added to set!"); else System.out.println(" Duplicate already in set. Not added to set!"); } Iterator it = myDatesHashSet.iterator(); System.out.println("Here are your unique random dates in the set: "); while (it.hasNext()) System.out.print(it.next() + " "); System.out.println(); System.exit(0); } //generate a random Date or IncDate. //between m1/d1/y1 and m2/d2/y2 // public static Date generateRandomDate(int y1, int m1, int d1, int y2, int m2, int d2) { public static Date generateRandomDate() { int year, month, day=0; // year = (int)(Math.random()*); year = 2000; //month = (int)(Math.random()*12+1); month = 1; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: //day = (int)(Math.random()*31+1); day = (int)(Math.random()*10+1); break; case 4: case 6: case 9: case 11: day = (int)(Math.random()*30+1); break; case 2: if (year%4==0 && year%100!=0 || year%400==0) //leap year test day = (int)(Math.random()*29+1); else day = (int)(Math.random()*28+1); break; } //*** 50 50 whether it's Date or IncDate if (Math.random() < .5) return new Date(month,day,year); else return new IncDate(month,day,year); } } class Date //same as in ch01. ***added equals() and hashCode() { protected int year; protected int month; protected int day; public Date(int newMonth, int newDay, int newYear) { month = newMonth; day = newDay; year = newYear; } public int yearIs() { return year; } public int monthIs() { return month; } public int dayIs() { return day; } public String toString() { return(month + "/" + day + "/" + year); } //***override equals() of Object. //***used to determine if two objects (of Date class) are "equal". //***MUST be overridden to use Date objects (uniquely, as keys) in a HashSet. //***equality is defined by this method. //***without this method, two objects are equal only if their references are the same. //***must be this signature: parameter MUST be type Object. public boolean equals( Object other ) { //parameter will be the other Date //***check that other really is Date, //**then (safely) downcast to Date to access instance variables if ((other instanceof Date) && ((((Date)other).year==year) && (((Date)other).month==month) && (((Date)other).day==day))) return true; else return false; //if other is null, or not a Date, or doesn't equal } //equals must be //1. reflexive: x.equals(x) is true //2. symmetric: x.equals(y) == y.equals(x) //3. transitive: if x.equals(y) and y.equals(z) then x.equals(z) //also: x.equals(null) is false //***override hashcode() of Object //***if two Dates are equal, they must have same hashcode. //***must be this signature: public int hashCode() { //return 1492; //works but inefficient //?? how to make good hash?? //some function of the instance variables modded by some prime return (year + month + day) % 101; } } class IncDate extends Date //same as in ch01 { public IncDate(int newMonth, int newDay, int newYear) { super(newMonth, newDay, newYear); } public void increment() { // increment algorithm goes here // it updates the year, month, and day attributes day = day + 1; } }