CS 1302 – Lab 10 This lab uses material from Chapter 21 (Sets and Maps). You will not turn this in unless you miss class the day we do it. Stage 1 1. Read (no action required) – TreeSet is another implementation of the Set interface. A TreeSet keeps its elements ordered with natural ordering or a comparator. As with HashSet there is no sequential access, but, as shown in the class diagram below it introduces a few methods that allow you to index into the set. For instance, headset(e) returns the set of elements that are less than e. 2. Establish a Workspace – Create a folder on your drive where you will put your lab or use an existing one. 3. Run Eclipse – At the prompt, navigate to your workspace. 4. Create a Project – We will create the Project for Lab 10. a. b. c. d. Choose: File, New, Java Project. Supply a project name, e.g. lab10_lastName Choose: Finish Choose: File, New, Package and supply the name “example1” 5. Download Code a. Download lab10.zip and unzip. b. Drag (or copy) all the files into the example1 folder. 1 6. Run Code a. b. c. d. Open the file TreeSetExamples.java Run the code. Carefully study the output to get a feel for what the code is doing. Carefully study the code in the hsExamples1 method and correlate with the output. 7. Above, we showed that TreeSet is-a Set. Actually, there are two interfaces in between (as shown in the class diagram on the right) that prescribe the behaviors we saw in TreeSet . We first consider a few of the methods specified in the SortedSet interface: Method first() last() headSet(toElement:E) tailSet(fromElement:E) subSet(fromElement:E, toElement:E) Description The first (smallest) element is returned The last (largest) element is returned The set of elements that are strictly less than toElement. {x|x<toElement} The set of elements greater than or equal to fromElement. {x|x>=fromElement} The set of elements between fromElement, inclusive to toElement exclusive. {x|fromElement <= x < toElement} The return from the last three methods is a SortedSet 8. Copy this code to the bottom of the treeSetExample method. System.out.println("\nfirst(): " + tsCities.first()); System.out.println("last(): " + tsCities.last()); SortedSet<String> ssHead = tsCities.headSet("New York"); System.out.println("headSet(\"New York\"): " + ssHead); SortedSet<String> ssTail = tsCities.tailSet("New York"); System.out.println("tailSet(\"New York\"): " + ssTail); System.out.println("tailSet(\"New Amsterdam\"): " + tsCities.tailSet("New Amsterdam")); System.out.println("tailSet(\"New Zeland\"): " + tsCities.tailSet("New Zeland")); System.out.println("subSet(\"Chicago\", \"Pitsburg\"): " + tsCities.subSet("Chicago", "Pitsburg")); System.out.println("subSet(\"London\", \"New York\"): " + tsCities.subSet("London", "New York")); 9. Run code and verify output. 2 10. Next, we consider a few of the methods specified in the NavigableSet interface. Method floor(e:E) lower(e:E) ceiling(e:E) higher(e:E) pollFirst() pollLast() Description The largest element <= e is returned The largest element < e is returned The smallest element >= e is returned The smallest element > e is returned Returns the smallest element and removes it Returns the largest element and removes it 11. Copy this code to the bottom of the treeSetExample method. System.out.println("\nThe TreeSet: " + tsCities); System.out.println("lower(\"Pitsburg\"): " + tsCities.lower("Pitsburg")); System.out.println("lower(\"New York\"): " + tsCities.lower("New York")); System.out.println("higher(\"Moab\"): " + tsCities.higher("Moab")); System.out.println("higher(\"New York\"): " + tsCities.higher("New York")); System.out.println("\nThe TreeSet: " + tsCities); System.out.println("floor(\"Pitsburg\"): " + tsCities.floor("Pitsburg")); System.out.println("floor(\"New York\"): " + tsCities.floor("New York")); System.out.println("ceiling(\"Moab\"): " + tsCities.ceiling("Moab")); System.out.println("ceiling(\"New York\"): " + tsCities.ceiling("New York")); System.out.println("\nThe TreeSet: " + tsCities); System.out.println("pollFirst(): " + tsCities.pollFirst()); System.out.println("pollLast(): " + tsCities.pollLast()); System.out.println("New tree set: " + tsCities); 12. Run code and verify output. Stage 2 1. Read (no action required) – Next, we consider an Employee class and three Comparator<Employee> classes (provided in download) which compare Employee objects based on Name, Salary, and SSN, respectively. As shown in the class diagram above, TreeSet defines a constructor that takes a Comparator which of course defines the ordering of the elements in the set. Thus, we can create TreeSets that order Employee objects on Name, Salary, and SSN: TreeSet<Employee> tsEmpsName = new TreeSet<>( new EmployeeNameComparator() ); TreeSet<Employee> tsEmpsSSN = new TreeSet<>( new EmployeeSSNComparator() ); TreeSet<Employee> tsEmpsSalary = new TreeSet<>( new EmployeeSalaryComparator() ); 3 Let’s look more carefully at the constructor: public TreeSet(Comparator<? super E> c) {...} The expression, <? super E> is a lower bound wildcard which means E or any supertype of E. For the TreeSet constructor, a parameter c is a Comparator defined on the Employee class or any superclass of Employee. For example, suppose Employee is a subclass of Person and we have a Comparator defined on Person, then we can use an instance of this Comparator to create a TreeSet<Employee>. If the constructor were defined: public TreeSet(Comparator<E> c) {...} then this would require that the Comparator be defined on the Employee class. 2. Find the main and comment out the call to treeSetExample and uncomment the call to treeSetExample2. 3. Find the treeSetExample2 method and study the code there. Run code and verify output. 4. Read (no action required) – How do we find all Employee objects in a TreeSet ordered on Salary that have a salary of 23.0 or more? Answer: we use the tailSet method. But, look at the signature of the tailSet method in the class diagram above. It takes an argument of type E, which in this case is an Employee. But how do we create an Employee? An Employee has a name, a salary, and a SSN. I don’t know all these. All I know is that I want a salary of 23.0 or more. A trick is to use a dummy Employee, one that just has a salary (and not a name or SSN). Thus, for the Employee class we have defined a constructor that accepts all fields: public Employee(String lName, String fName, int ssNum, double salary) { this.lName = lName; this.fName = fName; this.ssNum = ssNum; this.salary = salary; } And, we have defined another constructor that just accepts a salary: public Employee(double salary) { this.salary = salary; } Thus, we can use this dummy Employee as the “key” in the tailSet search: // Create TreeSet of Employees ordered on Salary TreeSet<Employee> tsEmpsSalary = new TreeSet<>( new EmployeeSalaryComparator() ); // Add some Employees tsEmpsSalary.add(new Employee("Gibson", "Dave", 12345678, 83.0)); ... // Create “dummy” Employee Employee empKey = new Employee(23.0); // Find tailSet using “dummy” Employee SortedSet<Employee> ssHighSalaries = tsEmpsSalary.tailSet(empKey); 4 5. Copy this code to the bottom of the treeSetExample2 method. Employee empKey = new Employee(23.0); SortedSet<Employee> ssHighSalaries = tsEmpsSalary.tailSet(empKey); System.out.println("\nEmployees larger than: " + empKey); printSet(ssHighSalaries); 6. Run code and verify output. Stage 3 Now it is your turn to work a few problems. 1. Write a method, getCommonWords that accepts two Lists of words (strings) and returns a new alphabetized List with just the words in common. For example, if these are the input lists: List<String> words1 = new ArrayList<>(Arrays.asList("d", "c", "b", "g", "b")); List<String> words2 = new ArrayList<>(Arrays.asList("f", "d", "b", "g", "g")); Then the output of the method would be: [b, d, g] Open MyExamples.java and write this method. In main, add a line of code to call the method and print the return. 2. A Blob has an age and a volume (both ints). Write a method, getBlobsOlderThan that accepts a List of Blobs and an age. This list can have duplicate Blobs where Blobs are considered duplicates if they have the same age, no matter what the volume is. This method will return a SortedSet of Blobs such that there are no duplicates and only Blobs with an age at or above age. For example, if we call this method with the list of Blobs below and age=10: blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new blobs1.add(new Blob(11,65)); Blob(5,8)); Blob(4,9)); Blob(35,7)); Blob(6,3)); Blob(8,55)); Blob(6,14)); Blob(4,21)); Blob(14,4)); Blob(23,7)); Then, the return will be: [(age=11:volume=65), (age=14:volume=4), (age=23:volume=7), (age=35:volume=7)] Open MyExamples.java and write the method described above. You have been provided a Blob class and a BlobAgeComparator. 5