**Old Code**

`class Set { private Comparable[] members; //using an array of Comparable means that any object of a class that //implements Comparable can be placed in this array private int count; private static final int DEFAULT_LENGTH = 10; //reminder: static means this is a variable that //is a constant (its final) that is part of the class specification but //not part of the objects that this class makes private static final String NL = System.getProperty("line_separator");`

private int memberLocation; //conatains the location of the last found isMemberpublic Set() [ members = new Comparable[DEFAULT_LENGTH]; count = 0; memberLocation = -1; } public Set(int length){ members = new Comparable[length]; count = 0; memberLocation = -1; } public void add(Comparable newItem){//Should do this check first because don't want to do anything if can't add newItemif (isMember(newItem)) //keeping a set so don't want to allow duplicates, exit method return; if (count == members.length) grow(); int index; //has scope outside for loop for (index = count; index > 0; index--){ int difference = members[index-1].compareTo(c); //note: difference should never equal 0 if (difference > 0) members[index] = members[index-1]; if (difference < 0) break; } members[index] = newItem; } private void grow() { Comparable[] biggerArray = new Comparable[2*members.length]; for (int index = 0; index < count; index++){ biggerArray[index] = members[index]; } members = biggerArray; } //this does the same thing as the isMember we wrote in the last class public boolean isMember(Comparable item) { return isMember(Comparable item, 0); }//modified isMember so that can shrink the size of the set it has to searchprivate boolean isMember(Comparable item, int initalLeft) { int left = initalLeft; int right = count-1; int pivot = left + (right-left)/2; while(right >= left) { int difference = members[pivot].compareTo(item); if (difference == 0) { memberLocation = pivot; return true; } if (difference > 0) right = pivot-1; if (difference < 0){ left = pivot +1; memberLocation = pivot; } pivot = left + (right-left)/2 } if (memberLoction < 0) memberLocation = 0; return false; } /////////////////////NEW CODE////////////////////// public String toString() { String retString = ""; //simple transversal of the array...adding each object into the retString for (int index = 0; index < count; index++) { //assuming that all objects in array have overridden the toString method retString += members[index] + NL; } return retString; }

Remember from math that the union of two sets consists of all objects that appear in either of the two sets (and since they are sets their are no repeats of the objects.) So, our union takes an array (to create a union with the main array in the class) and returns a new Set that contains all elements that are in either of the two arrays (while avoiding repeating/ duplicting an object). A way you can do this is to copy the first set then iterate through the second set and add to the copied set all objects that aren't members of the copied set already.

Note that our add method all ready checks for duplicates so the easiest code would be:

However, if we assume that we have an add method that looks like this:`public Set union(Set otherSet) { Set unionSet = new Set (this);//this is a copy constructor that makes a copy of //the Set. for (int index = 0; index < count; index++) { unionSet.add(otherSet.members[index]); } } //our copy constructor... public Set(Set sourceSet) { members = new Comparable [sourceSet.members.length] //this will get the length of the //sourceSet's member array (even though member is private we can do this //because private instance variables can be accessed by other objects of the //same class. count = sourceSet.count; memberLocation = -1; //now copy all of the objects into our new array (simple transversal) for (int index = 0; index < count; index++) { members[index] = sourceSet.members[index]; } }`

We would have to call isMember() before adding the new object. Like so:`public void alwaysAdd(Comparable newItem){ //note lack of check for duplicates if (count == members.length) grow(); int index; //has scope outside for loop for (index = count; index > 0; index--){ int difference = members[index-1].compareTo(c); //note: difference should never equal 0..otherwise you have passes in a duplicate if (difference > 0) members[index] = members[index-1]; if (difference < 0) break; } members[index] = newItem; }`

`public Set union(Set otherSet) { Set unionSet = new Set (this);//this is a copy constructor that makes a copy of //the Set. for (int index = 0; index < count; index++) { if (! unionSet.isMember(otherSet.members[index])) unionSet.alwaysAdd(otherSet.members[index]); } }`

This code will do the correct job. However, it isn't the best that we can do. A binary search is the best way to look for an element (assuming that we are looking for a random element in an ordered array). Since we are looking at two sets that are both ordered we can do better than a binary search.You can go through the lists at the same time, keeping in mind that since they are ordered the next number that you are looking for won't be prior to the last possible contender for the last search. As you go through the sets compare one set to the other by keeping a referance in each of the sets which refers to the numbers you just compared, and continue searching as long as a variable's referance is less than the other's (aka less than the value being searched for).

You can also do a binary search on the elements left over in the second set after the previous search. Since a binary search is the quickest way to search a set this is the quickest way to search (as long as you don't always start back at the begining). So keeping in mind that the sets are ordered the most efficent search would be a binary search limited by the previous left bound (or where the last member was found to be equal). You should never start earlier than where you left off!

With that in mind go back to the top of the lecture and relook at isMember(). It has been modified so that it stores what the last left was (and if it returned true then memberLocation is the pivot or points to where the equal memeber was) in a new instance variable memberLocation (so it has scope in all of the methods in our program). memeberLocation is the key to shortening our search time. Because memberLocation always points to an object less than or equal to what we were last looking for memberLocation is where we should start our search. (Notice that memberLocation treads on the side of caution and is typically one less than the last left bound...allowing for the margin of error when right crosses left).

`public Set union(Set otherSet) { Set unionSet = new Set (this); for (int index = 0; index < count; index++) { if (! unionSet.isMember(otherSet.members[index], memberLocation)) unionSet.alwaysAdd(otherSet.members[index]); } } }`