|
Java Programming Language Basics: Using Sorting in Applications
Java Bits: Identify Culturally Dependent Data
Making Sense of the Java Class Libraries: The Collator and CollationKey Classes
Program Challenge: Create a Sorting Application
Take an Online Quiz: Test what you learned
New to Java Technology Programming Center Updates: SunEd Web and Instructor Led Java Technology Courses
For More Information: Read articles, Tech Tips, trails, and tutorials that provide more information on the topics discussed here.
Java Programming Language Basics
Using Sorting in Applications
Sorting support is built into the standard libraries of the Java platform. You can make your own classes
sortable, and redesign third-party classes to be sortable if they weren't originally.
Support for sorting starts with the Comparable interface. A single method interface defined in the java.lang package:
public interface Comparable {
public int compareTo(Object o);
}
If a class implements the Comparable interface, it is directly sortable. That's really all there is to sorting a series of instances of the system classes that implement the interface. Those systems classes are as follows:
BigDecimal, BigInteger, Byte, ByteBuffer, Character, CharBuffer, Charset, CollationKey, Date, Double, DoubleBuffer, File, Float, FloatBuffer, IntBuffer, Integer, Long, LongBuffer, ObjectStreamField, Short, ShortBuffer, String, URI
To demonstrate, the following program sorts a series of String objects that are commandline arguments. It uses the sort method of the java.util.Arrays class to reorder the elements of the command-line argument array.
import java.util.Arrays;
public class SortArgs {
public static void main(String args[]) {
printArray(args, "Before");
Arrays.sort(args);
printArray(args, "After");
}
private static void printArray(String array[], String header) {
System.out.println("\n\n" + header);
for (int i=0, n=array.length; i<n; i++) {
System.out.println(i + ": " + array[i]);
}
}
}
If you were to run the program with the following command line:
java SortArgs one two three four five
You'd get the following results:
Before
0: one
1: two
2: three
3: four
4: five
After
0: five
1: four
2: one
3: three
4: two
It really is that simple to sort system classes.
For your own classes, you can implement Comparable. As you'll recall in the interface, the compareTo method returns an int. By providing a compareTo method that returns the proper value when comparing two instances of your own class, you can make your classes Comparable. And what are those return values? The easy one is for when two classes are equal. That causes compareTo to return a value of zero (0). When the specific instance of the class is logically less than the passed in instance, compareTo returns a negative number (like -1). That leaves > to be a positive number. One other thing needs to be added though. The compareTo method is only defined to work when comparing equivalent classes. If the object passed in isn't equvalent, a ClassCastException is thrown.
To demonstrate, let us define a Name object with a first name and last name. Name is sortable with last name first. So, in the compareTo method, you essentially need to bundle two compareTo calls, one for each variable, where the second is only called if the first is equal.
public class Name implements Comparable {
private String lastName;
private String firstName;
public Name(String first, String last) {
firstName = first;
lastName = last;
}
public int compareTo(Object o) {
// This automatically throws exception if wrong type
Name other = (Name)o;
int returnValue = lastName.compareTo(other.lastName);
if (returnValue == 0) {
returnValue = firstName.compareTo(other.firstName);
}
return returnValue;
}
public String toString() {
return "Name[" + lastName + "," + firstName + "]";
}
}
To test the program, the following example creates several names, sorts them, and prints out the before and after sorted order.
import java.util.Arrays;
public class SortName {
public static void main(String args[]) {
Name names[] = {
new Name("John", "Doe"),
new Name("Jane", "Doe"),
new Name("Mary", "Jane"),
new Name("Mary", "Doe"),
new Name("John", "Smith"),
new Name("Mary", "Smith"),
};
printArray(names, "Before");
Arrays.sort(names);
printArray(names, "After");
}
private static void printArray(Name array[], String header) {
System.out.println("\n\n" + header);
for (int i=0, n=array.length; i<n; i++) {
System.out.println(i + ": " + array[i]);
}
}
}
Notice how the results show the names sorted in proper order.
Before
0: Name[Doe,John]
1: Name[Doe,Jane]
2: Name[Jane,Mary]
3: Name[Doe,Mary]
4: Name[Smith,John]
5: Name[Smith,Mary]
After
0: Name[Doe,Jane]
1: Name[Doe,John]
2: Name[Doe,Mary]
3: Name[Jane,Mary]
4: Name[Smith,John]
5: Name[Smith,Mary]
The last thing to mention is what to do when you need to sort instances of a class where the original class designer didn't implement Comparable, or if you don't like the sort order originally defined. By creating your own java.util.Comparator (or reusing one previously defined), you can define your own sorting mechanism.
For instance, by default, instances of the String class are sorted in case sensitive order, so that Smith, sMith, and smith are not equivalent. If you'd like to sort in a case insensitive manner, you can ask the String class for its CASE_INSENSITIVE_ORDER Comparator.
By making a quick change to the SortArgs program, and adding the optional second argument of a Comparator to the Arrays.sort call, the following code demonstrates the use of a Comparator:
import java.util.Arrays;
import java.util.Comparator;
public class SortArgs2 {
public static void main(String args[]) {
printArray(args, "Before");
Arrays.sort(args);
printArray(args, "After");
Comparator comp = String.CASE_INSENSITIVE_ORDER;
Arrays.sort(args, comp);
printArray(args, "Insensitive");
}
private static void printArray(String array[], String header) {
System.out.println("\n\n" + header);
for (int i=0, n=array.length; i<n; i++) {
System.out.println(i + ": " + array[i]);
}
}
}
A command line as follows:
java SortArgs2 one2 One3 oNe1 ONE Two
generates the following results:
Before
0: one2
1: One3
2: oNe1
3: ONE
4: Two
After
0: ONE
1: One3
2: Two
3: oNe1
4: one2
Insensitive
0: ONE
1: oNe1
2: one2
3: One3
4: Two
Notice the difference between the original After results and the Insensitive results.
For those classes that aren't Comparable, you define a Comparator and provide that to the Arrays.sort method. Or, as previously mentioned, just change the default sort order.
To demonstrate, add getFirstName and getLastName methods to the Name class:
public class Name implements Comparable {
private String lastName;
private String firstName;
public Name(String first, String last) {
firstName = first;
lastName = last;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int compareTo(Object o) {
// This automatically throws exception if wrong type
Name other = (Name)o;
int returnValue = lastName.compareTo(other.lastName);
if (returnValue == 0) {
returnValue = firstName.compareTo(other.firstName);
}
return returnValue;
}
public String toString() {
return "Name[" + lastName + "," + firstName + "]";
}
}
Now, change the original name-sorting example to do first name first, instead of the original last name first. The compare method of Comparator works similarly to the compareTo method of Comparable, returning signed numbers to determine positioning. The one difference being that compareTo takes two arguments, instead of one, as both objects to compare must be passed in for comparison.
import java.util.Arrays;
import java.util.Comparator;
public class SortName2 {
public static void main(String args[]) {
Name names[] = {
new Name("John", "Doe"),
new Name("Jane", "Doe"),
new Name("Mary", "Jane"),
new Name("Mary", "Doe"),
new Name("John", "Smith"),
new Name("Mary", "Smith"),
};
printArray(names, "Before");
Comparator comp = new Comparator() {
public int compare(Object o1, Object o2) {
// This automatically throws exception if wrong type
Name first = (Name)o1;
Name second = (Name)o2;
int returnValue =
first.getFirstName().compareTo(second.getFirstName());
if (returnValue == 0) {
returnValue =
first.getLastName().compareTo(second.getLastName());
}
return returnValue;
}
};
Arrays.sort(names, comp);
printArray(names, "After");
}
private static void printArray(Name array[], String header) {
System.out.println("\n\n"+header);
for (int i=0, n=array.length; i<n; i++) {
System.out.println(i + ": " + array[i]);
}
}
}
Running the sample program now produces the following output:
Before
0: Name[Doe,John]
1: Name[Doe,Jane]
2: Name[Jane,Mary]
3: Name[Doe,Mary]
4: Name[Smith,John]
5: Name[Smith,Mary]
After
0: Name[Doe,Jane]
1: Name[Doe,John]
2: Name[Smith,John]
3: Name[Doe,Mary]
4: Name[Jane,Mary]
5: Name[Smith,Mary]
Since the toString method hasn't changed, last names are still printed first. However, notice that the names are now sorted with first name first, not last.
Java Bits
Identify Culturally Dependent Data
by Monica Pawlan
To internationalize an application, the first thing you need to do is identify the culturally dependent data in your application. Culturally-dependent data is any data that varies from one culture or country to another. Text is the most obvious and pervasive example of culturally dependent data, but other things like number formats, sounds, times, and dates should be considered too.
Read More
Making Sense of the Java Class Libraries
The Collator and CollationKey Classes
Applications sort through text by performing frequent string comparisons. If your application audience is limited to people who speak English, you can perform string comparisons with the String.compareTo method, which performs a binary comparison of the Unicode characters within the strings.
For most languages, however, this binary comparison is reliable because the Unicode values do not correspond to the relative order of the characters.
Fortunately, the Collator class enables your application to perform String comparisons for different languages. Using the predefined collation rules provided by the Collator class, you can sort strings in a locale-independent manner.
Collator is an abstract base class. Subclasses implement specific collation strategies. Other subclasses may be created to handle more specialized needs.
Like other locale-sensitive classes, you can use the static factory method, getInstance, to obtain the appropriate Collator object for a given locale.
The following example shows how to compare two strings using the Collator for the default locale.
// Compare two strings in the default locale
Collator myCollator = Collator.getInstance();
if( myCollator.compare("dog", "DOG") < 0 )
System.out.println("dog is less than DOG.");
else
System.out.println("dog is greater than or equal to DOG.");
A CollationKey represents a String under the rules of a specific Collator object. Comparing two CollationKeys returns the relative order of the Strings they represent. Using CollationKeys to compare Strings is generally faster than using Collator.compare. When the Strings must be compared multiple times, it's more efficient to use CollationKeys.
You can not create CollationKeys directly. Create them by calling Collator.getCollationKey. You can only compare CollationKeys generated from the same Collator object.
Collator.compare examines only as many characters as it needs, which makes it faster when doing single comparisons.
The following example shows how CollationKeys might be used to sort a list of Strings.
// Create an array of CollationKeys for the Strings to be sorted.
Collator myCollator = Collator.getInstance();
CollationKey[] keys = new CollationKey[3];
keys[0] = myCollator.getCollationKey("Tom");
keys[1] = myCollator.getCollationKey("Dick");
keys[2] = myCollator.getCollationKey("Harry");
sort( keys );
//...
// Inside body of sort routine, compare keys this way
if( keys[i].compareTo( keys[j] ) > 0 )
// swap keys[i] and keys[j]
//...
// Finally, when we've returned from sort.
System.out.println( keys[0].getSourceString() );
System.out.println( keys[1].getSourceString() );
System.out.println( keys[2].getSourceString() );
Program Challenge
Create a Sorting Application
Create a program that offers the ability to sort the lines in a JTextArea.
Use one of the following options:
- Regular String sorting, using its built in
Comparable interface
- Case-insensitive
Comparator
- A
Collator
See a possible solution to the Challenge
Take an Online Quiz
Test what you learned about sorting.
New to Java Technology Programming Center
SunEd Web and Instructor Led Java Technology Courses
The Fundamentals of the Java Programming Language course focuses on the significance of object-oriented programming, the keywords, and constructs of the Java programming language, and the steps required to design and develop and test simple Java programs.
Web-based
Instructor led
For More Information
Comparing Strings
Class Collator
Essentials of the Java Programming Language
Downloading the Java 2 Platform
For most Java development, you need the class libraries, compiler, tools, and runtime environment provided with the J2SE development kit.
Subscribe to the following newsletters for the latest information about technologies and products in other Java platforms:
- Core Java Technologies Newsletter. Learn about new products, tools, resources, and events of interest to developers working with core Java technologies.
- Wireless Developer Newsletter. Learn about the latest releases, tools, and resources for developers working on wireless and Java Card technologies and applications.
- Core Java Technologies Tech Tips (formerly JDC Tech Tips) Get expert tips, sample code solutions, and techniques for developing in the Java 2 Platform, Standard Edition (J2SE)
You can subscribe to these and other JDC publications on the JDC Newsletters and Publications page
IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developer.java.sun.com/berkeley_license.html
Comments? Send your feedback on the Java Technology Fundamentals Newsletter to: dana.nourie@sun.com
Go to the subscriptions page to subscribe or unsubscribe to this newsletter.
ARCHIVES: You'll find the Java Technology Fundamentals Newsletter archives at:
http://developer.java.sun.com/developer/onlineTraining/new2java/supplements/
Copyright 2003 Sun Microsystems, Inc. All rights reserved. 4150 Network Circle, Santa Clara, CA 95054
Trademark Information: http://www.sun.com/suntrademarks/
Java, J2EE, J2SE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.
|