| CS 535: Object-Oriented Programming & Design |
|
---|
Fall Semester, 1997
Doc 13, Sorting - An Example
To Lecture Notes Index
San Diego State University -- This page last updated 05-Oct-97
Contents of Doc 13, Sorting - An Example
- References
- Sorting - An Example
- Solution 1
- Sort Solution 2
- Inheritance verses Object Composition
- A Better SortedList - Override Compare Method
- Problems with BetterSortedList
- Solution 3 - Create Comparer Class
- Sorting in Other Languages
- Languages and Countries Available
Design Patterns: Elements of Resuable Object-Oriented Software, Gamma,
Helm, Johnson, Vlissides, Addision-Wesley, 1995
On-line Java 1.1.3 API Documentation
Vague Goal - Produce a general purpose sorter
Use interface Comparable and Sort class
/**
* Comparable interface contains the methods that
* a class must implement if you want the sort method to
* sort objects of that class
*/
interface Comparable
{
/**
* Returns true if current object is less than otherObject
*/
public boolean lessThan( Comparable otherObject );
public boolean greaterThan( Comparable otherObject );
public boolean equal( Comparable otherObject );
}
Example use of Comparable - StudentRecord
class StudentRecord implements Comparable
{
private final int ID;
private String name;
private float GradePointAverage;
public StudentRecord( int uniqueID, String studentName)
{
name = studentName;
ID = uniqueID;
}
public String toString() { return name; }
public boolean lessThan( Comparable aStudent )
{
StudentRecord otherStudent =
(StudentRecord) aStudent;
return ID < otherStudent.ID;
}
public boolean greaterThan( Comparable aStudent )
{
StudentRecord otherStudent = (StudentRecord) aStudent;
return ID > otherStudent.ID;
}
public boolean equal( Comparable aStudent )
{
StudentRecord otherStudent = (StudentRecord) aStudent;
return ID == otherStudent.ID;
}
}
Using StudentRecord
class Test
{
public static void main( String args[] )
{
StudentRecord goodStudent =
new StudentRecord( 1, "Roger");
StudentRecord bestStudent =
new StudentRecord( 2, "Sam");
if ( goodStudent.greaterThan( bestStudent ) )
System.out.println( "good is greater" );
else
System.out.println( "good is less" );
}
}
Output
good is less
Sorter
class Sorter
{
public static final void sort( Comparable[] list )
{
for ( int unsortedElementIndex = 1;
unsortedElementIndex < list.length;
unsortedElementIndex++
)
{
Comparable insertMe;
insertMe = list[ unsortedElementIndex ];
int insertIndex = unsortedElementIndex;
while ( (insertIndex > 0) &&
list[ insertIndex - 1 ].greaterThan( insertMe )
)
{
list[insertIndex] = list[insertIndex-1];
insertIndex--;
}
list[insertIndex] = insertMe;
}
} // end sort
} // end class
Using Sorter
class Test
{
public static void main( String args[] )
{
StudentRecord[] classList = new StudentRecord[ 4];
classList[0] = new StudentRecord( 5, "Roger");
classList[1] = new StudentRecord( 2, "Roberto");
classList[2] = new StudentRecord( 8, "Victor");
classList[3] = new StudentRecord( 3, "Sergio");
Sorter.sort( classList );
for ( int studentIndex = 0;
studentIndex < classList.length;
studentIndex++
)
System.out.println( classList[studentIndex]);
}
}
Output
Roberto
Sergio
Roger
Victor
What is Wrong with Sorter?
What Operations would you want on a SortedList?
The Plot Thickens
There are times when you want to sort a list of StudentRecords by:
- Id
- Name
- Grade
SortedList Class - contains all the great methods listed on previous slide
SortByName - contains one method which sorts by name
SortByID - contains one method which sorts by ID
SortByGrade - contains one method which sorts by Grade
SortedList
abstract class SortedList
{
private Vector list;
public SortedList( int size )
{
list = new Vector( size);
}
public Enumeration elements()
{
return list.elements();
}
public String toString()
{
return list.toString();
}
public Object elementAt( int index)
{
return list.elementAt( index);
}
public void addElement( Object addMe )
{
list.addElement( addMe);
sort( list);
}
abstract protected void sort( Vector unsorted);
}
Some useful methods not included to save space
SortedList Subclasses
class SortByID extends SortedList
{
public SortByID( int size)
{
super(size);
}
protected void sort( Vector list)
{
for ( int newItemIndex = 1;
newItemIndex < list.size();
newItemIndex++
)
{
StudentRecord insertItem = (StudentRecord)
list.elementAt( newItemIndex );
int insertIndex = newItemIndex;
while (insertIndex > 0)
{
StudentRecord nextItem = (StudentRecord)
list.elementAt(insertIndex - 1 );
if ( nextItem.getID() > insertItem.getID() )
{
list.setElementAt(
list.elementAt( insertIndex -1),
insertIndex);
insertIndex--;
}
else
break;
}
list.setElementAt( insertItem, insertIndex) ;
}
}
}
SortedList Subclasses
class SortByName extends SortedList
{
public SortByName( int size)
{
super(size);
}
protected void sort( Vector list)
{
for ( int newItemIndex = 1;
newItemIndex < list.size();
newItemIndex++ )
{
StudentRecord insertItem = (StudentRecord)
list.elementAt( newItemIndex );
int insertIndex = newItemIndex;
while (insertIndex > 0)
{
StudentRecord nextItem = (StudentRecord)
list.elementAt(insertIndex - 1 );
if ( nextItem.getName().compareTo(
insertItem.getName()) > 0 )
{
list.setElementAt(
list.elementAt( insertIndex -1),
insertIndex);
insertIndex--;
}
else
break;
}
list.setElementAt( insertItem, insertIndex) ;
}
}
}
Sample use of SortedList
class Test
{
public static void main( String args[] )
{
SortedList list = new SortByName( 4);
list.addElement( new StudentRecord( 5, "Roger") );
list.addElement( new StudentRecord( 2, "Roberto"));
list.addElement( new StudentRecord( 8, "Victor"));
list.addElement( new StudentRecord( 3, "Sergio"));
System.out.println( list);
Enumeration students = list.elements();
SortedList id = new SortByID( 4 );
while (students.hasMoreElements() )
id.addElement( students.nextElement() );
System.out.println( id);
}
}
Output
[Roberto, Roger, Sergio, Victor]
[Roberto, Sergio, Roger, Victor]
Why not Subclass Vector?
abstract class SortedList extends Vector
{
public SortedList( int size )
{
super( size);
}
public void addElement( Object addMe )
{
list.addElement( addMe);
sort( list);
}
abstract protected void sort( Vector unsorted);
}
Object Composition
- Class B has a field of type class A
- Class A is a black box to class B
- More flexible than inheritance
Inheritance
- Class B is a subclass of A
- Simpler to use
- Class B can get involved with inner workings of A
abstract class BetterSortedList
{
private Vector list;
public SortedList( int size )
{
list = new Vector( size);
}
public Enumeration elements()
{
return list.elements();
}
public String toString()
{
return list.toString();
}
public Object elementAt( int index)
{
return list.elementAt( index);
}
public void addElement( Object addMe )
{
list.addElement( addMe);
sort( list);
}
//BetterSortedList Continued
protected void sort( Vector list)
{
for ( int newItemIndex = 1;
newItemIndex < list.size();
newItemIndex++
)
{
StudentRecord insertItem =
(StudentRecord) list.elementAt( newItemIndex );
int insertIndex = newItemIndex;
while ( (insertIndex > 0) &&
isGreaterThan( list.elementAt( insertIndex - 1),
insertItem
)
)
{
list.setElementAt( list.elementAt( insertIndex -1),
insertIndex
);
insertIndex--;
}
list.setElementAt( insertItem, insertIndex) ;
}
}
abstract protected boolean
isGreaterThan( Object a, Object b);
}
BetterSortedList Subclasses
class SortByID extends BetterSortedList
{
public SortByID( int size)
{
super(size);
}
protected boolean isGreaterThan( Object a, Object b)
{
int leftOperand = ((StudentRecord) a).getID();
int rightOperand = ((StudentRecord) b).getID();
return leftOperand > rightOperand;
}
}
class SortByName extends SortedList
{
public SortByName( int size)
{
super(size);
}
protected boolean isGreaterThan( Object a, Object b)
{
String leftOperand = ((StudentRecord) a).getName();
String rightOperand = ((StudentRecord) b).getName();
if ( leftOperand.compareTo( rightOperand) > 0 )
return true;
else
return false;
}
}
Sample use of BetterSortedList
class Test
{
public static void main( String args[] )
{
BetterSortedList list = new SortByName( 4);
list.addElement( new StudentRecord( 5, "Roger") );
list.addElement( new StudentRecord( 2, "Roberto"));
list.addElement( new StudentRecord( 8, "Victor"));
list.addElement( new StudentRecord( 3, "Sergio"));
System.out.println( list);
Enumeration students = list.elements();
SortedList id = new SortByID( 4 );
while (students.hasMoreElements() )
id.addElement( students.nextElement() );
System.out.println( id);
}
}
How does one sort a list of students by name and ID in the same program?
Since isGreaterThan is not part of student, but a sort class, can't use it in
other comparisons of student record
public abstract class Comparer
{
public abstract boolean lessThan( Object leftOperand,
Object rightOperand );
public abstract boolean greaterThan( Object leftOperand,
Object rightOperand );
public abstract boolean equals( Object leftOperand,
Object rightOperand );
public boolean lessThanOrEqual( Object leftOperand,
Object rightOperand )
{
if ( lessThan( leftOperand, rightOperand) ||
equals( leftOperand, rightOperand)
)
return true;
else
return false;
}
public boolean greaterThanOrEqual( Object leftOperand,
Object rightOperand )
{
if ( greaterThan( leftOperand, rightOperand) ||
equals( leftOperand, rightOperand)
)
return true;
else
return false;
}
}
StudentRecord Comparers
class StudentIDComparer extends Comparer
{
private int getID( Object student )
{
return ((StudentRecord) student ).getID();
}
public boolean lessThan( Object leftOperand,
Object rightOperand )
{
int leftID = getID( leftOperand);
int rightID = getID( rightOperand);
return leftID < rightID;
}
public boolean greaterThan( Object leftOperand,
Object rightOperand )
{
int leftID = getID( leftOperand);
int rightID = getID( rightOperand);
return leftID > rightID;
}
public boolean equals( Object leftOperand,
Object rightOperand )
{
int leftID = getID( leftOperand);
int rightID = getID( rightOperand);
return leftID == rightID;
}
}
StudentRecord Comparers - Continued
class StudentNameComparer extends Comparer
{
private String getName( Object student )
{
return ((StudentRecord) student ).getName();
}
public boolean lessThan( Object leftOperand,
Object rightOperand )
{
String leftName = getName( leftOperand);
String rightName = getName( rightOperand);
if ( leftName.compareTo( rightName) < 0 )
return true;
else
return false;
}
public boolean greaterThan( Object leftOperand,
Object rightOperand )
{
String leftName = getName( leftOperand);
String rightName = getName( rightOperand);
if ( leftName.compareTo( rightName) > 0 )
return true;
else
return false;
}
//StudentRecord Comparers - Continued
public boolean equals( Object leftOperand,
Object rightOperand )
{
String leftName = getName( leftOperand);
String rightName = getName( rightOperand);
if ( leftName.compareTo( rightName) == 0 )
return true;
else
return false;
}
}
The SortedList using Comparers
class SortedList
{
private Vector list;
private Comparer listOrder;
public SortedList( int size, Comparer initialListOrder )
{
listOrder = initialListOrder;
list = new Vector( size);
}
public void setListOrder( Comparer newListOrder )
{
listOrder = newListOrder;
sort();
}
public Enumeration elements()
{
return list.elements();
}
public String toString()
{
return list.toString();
}
public Object elementAt( int index)
{
return list.elementAt( index);
}
public void addElement( Object addMe )
{
list.addElement( addMe);
sort();
}
//The SortedList using Comparers - Continued
protected void sort( )
{
for ( int newItemIndex = 1;
newItemIndex < list.size();
newItemIndex++
)
{
Object insertItem = list.elementAt( newItemIndex );
int insertIndex = newItemIndex;
while ( (insertIndex > 0) &&
listOrder.greaterThan(
list.elementAt( insertIndex - 1),
insertItem )
)
{
list.setElementAt( list.elementAt( insertIndex -1),
insertIndex);
insertIndex--;
}
list.setElementAt( insertItem, insertIndex) ;
}
}
}
The StudentRecord for use with Comparers
class StudentRecord
{
private final int ID;
private String name;
private float GradePointAverage;
public StudentRecord( int uniqueID, String studentName)
{
name = studentName;
ID = uniqueID;
}
public int getID()
{
return ID;
}
public String getName()
{
return name;
}
public String toString()
{
return name;
}
}
Sorting With Comparers
class Test
{
public static void main( String args[] )
{
SortedList list;
list = new SortedList( 4, new StudentNameComparer() );
list.addElement( new StudentRecord( 5, "Roger") );
list.addElement( new StudentRecord( 2, "Roberto"));
list.addElement( new StudentRecord( 8, "Victor"));
list.addElement( new StudentRecord( 3, "Sergio"));
System.out.println( list);
list.setListOrder( new StudentIDComparer() );
System.out.println( list);
}
}
Output
[Roberto, Roger, Sergio, Victor]
[Roberto, Sergio, Roger, Victor]
import java.text.Collator;
import java.util.Locale;
class TextComparer extends Comparer
{
private Collator textOrder;
public TextComparer()
{
textOrder = Collator.getInstance();
}
public TextComparer( Locale foreignLocation )
{
textOrder = Collator.getInstance( foreignLocation );
}
public static TextComparer spanish()
{
Locale spanish = new Locale( "es", "ES" );
return new TextComparer( spanish );
}
public boolean lessThan( Object leftOperand,
Object rightOperand )
{
String left = (String) leftOperand;
String right = (String) rightOperand;
if ( textOrder.compare( left, right) < 0 )
return true;
else
return false;
}
//TextComparer - Continued
public boolean greaterThan( Object leftOperand,
Object rightOperand )
{
String left = (String) leftOperand;
String right = (String) rightOperand;
if ( textOrder.compare( left, right) > 0 )
return true;
else
return false;
}
public boolean equals( Object leftOperand,
Object rightOperand )
{
String left = (String) leftOperand;
String right = (String) rightOperand;
if ( textOrder.compare( left, right) == 0 )
return true;
else
return false;
}
}
Using the SortedList
class Test
{
public static void main( String args[] )
{
SortedList list;
list = new SortedList( 4, TextComparer.spanish() );
list.addElement( "ch" );
list.addElement( "ca");
list.addElement( "cz");
list.addElement( "at" );
System.out.println( list);
}
}
Output
[at, ca, cz, ch]
Language | Country |
Arabic | Egypt |
Belorussian | Belarus |
Bulgarian | Bulgaria |
Catalan | Spain |
Czech | Czech Republic |
Danish | Denmark |
German | Germany |
German | Austria |
German | Switzerland |
Greek | Greece |
English | Canada |
English | United Kingdom |
English | Ireland |
English | United States |
Spanish - Modern Sort | Spain |
Estonian | Estonia |
Finnish | Finland |
French | France |
French | Belgium |
French | Canada |
French | Switzerland |
Croatian | Croatia |
Hungarian | Hungary |
Icelandic | Iceland |
Italian | Italy |
Italian | Switzerland |
Hebrew | Israel |
Japanese | Japan |
Korean | Korea |
Lithuanian | Lituania |
Latvian | Latvia |
Macedonian | Macedonia |
Dutch | Netherlands |
Dutch | Belgium |
Norwegian (BokmÂl) | Norway |
Norwegian (Nynorsk) | Norway |
Polish | Poland |
Portuguese | Portugal |
Romanian | Romania |
Russian | Russia |
Serbian (Latin) | Serbia |
Slovak | Slovakia |
Slovene | Slovenia |
Albanian | Albania |
Serbian (Cyrillic) | Serbia |
Swedish | Sweden |
Turkish | Turkey |
Ukrainian | Ukraine |
Chinese | China |
Chinese | ROC |
From the java.util.Locale API documentation:
You create a Locale object using one of the two constructors in this class:
- Locale(String language, String country)
- Locale(String language, String country, String variant)
The first argument to both constructors is a valid ISO Language Code. These
codes are the lower-case two-letter codes as defined by ISO-639. You can find a
full list of these codes at a number of sites, such as:
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
The second argument to both constructors is a valid ISO Country Code. These
codes are the upper-case two-letter codes as defined by ISO-3166. You can find
a full list of these codes at a number of sites, such as:
http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html