package org.limewire.collection; import java.io.File; import java.io.Serializable; import java.util.Comparator; /** * Provides a way to compare various data types with static methods. * <p> * <code>Comparators</code> is a utility class that uses the strategy * pattern for {@link java.lang.Comparable} instances. Many of these comparators * are only necessary because the Java 1.1.8 versions of their classes * did not implement the {@link Comparable} interface. * <p> * <code>Comparators</code> are helpful when using a {@link FixedsizePriorityQueue}. * <pre> FixedsizePriorityQueue<String> fpq = new FixedsizePriorityQueue<String>(Comparators.stringComparator(), 3); fpq.insert("Abby"); fpq.insert("Bob"); fpq.insert("Chris"); System.out.println(fpq); String s = fpq.insert("Dan"); System.out.println("Inserting another String pushes out an element (" + s + ") since the max. size was reached."); System.out.println(fpq); System.out.println("Minimum element: " + fpq.getMin()); System.out.println("Maximum element: " + fpq.getMax()); fpq.extractMax(); System.out.println(fpq); Output: [Abby, Bob, Chris] Inserting another String pushes out an element (Abby) since the max. size was reached. [Bob, Chris, Dan] Minimum element: Bob Maximum element: Dan [Bob, Chris] * </pre> */ public final class Comparators { /** * <code>Comparator</code> for comparing two <code>Integer</code>s. */ private static final Comparator<Integer> INT_COMPARATOR = new IntComparator(); /** * <code>Comparator</code> for comparing two <code>Integer</code>s the opposite way. */ private static final Comparator<Integer> INVERSE_INT_COMPARATOR = new InverseIntComparator(); /** * <code>Comparator</code> for comparing two <code>Long</code>s. */ private static final Comparator<Long> LONG_COMPARATOR = new LongComparator(); /** * Inverse <code>Comparator</code> for comparing two <code>Long</code>s. */ private static final Comparator<Long> INVERSE_LONG_COMPARATOR = new InverseLongComparator(); /** * <code>Comparator</code> for comparing two <code>String</code>s. */ private static final Comparator<String> STRING_COMPARATOR = new StringComparator(); /** * <code>Comparator</code> for comparing two <code>File</code>s. */ private static final Comparator<File> FILE_COMPARATOR = new FileComparator(); /** * <code>Comparator</code> for comparing two <code>String</code>s regardless of * case. */ private static final Comparator<String> CASE_INSENSITIVE_STRING_COMPARATOR = new CaseInsensitiveStringComparator(); private static final Comparator<Double> INVERSE_DOUBLE_COMPARATOR = new Comparator<Double>() { public int compare(Double a, Double b) { return b.compareTo(a); } }; /** * Ensure that this class cannot be constructed. */ private Comparators() {} /** * Instance assessor for the <code>Comparator</code> for <code>Integer</code>s. * This is necessary because the <code>Integer</code> class did not implement * <code>Comparable</code> in Java 1.1.8. This is an instance because the * <code>IntComparator</code> has no state, allowing a single instance to be * used whenever a <code>Comparator</code> is needed for <code>Integer</code>s. * * @return the <code>IntComparator</code> instance */ public static Comparator<Integer> integerComparator() { return INT_COMPARATOR; } public static Comparator<Integer> inverseIntegerComparator() { return INVERSE_INT_COMPARATOR; } /** * Instance assessor for the <code>Comparator</code> for <code>Long</code>s. This * is necessary because the <code>Long</code> class did not implement * <code>Comparable</code> in Java 1.1.8. This is an instance because the * <code>LongComparator</code> has no state, allowing a single instance to be * used whenever a <code>Comparator</code> is needed for <code>Long</code>s. * * @return the <code>LongComparator</code> instance */ public static Comparator<Long> longComparator() { return LONG_COMPARATOR; } /** * Instance assessor for the inverse <code>Comparator</code> for <code>Long</code>s. * This is necessary because the <code>Long</code> class did not implement * <code>Comparable</code> in Java 1.1.8. This is an instance because the * <code>LongComparator</code> has no state, allowing a single instance to be * used whenever a <code>Comparator</code> is needed for <code>Long</code>s. * * @return the <code>LongComparator</code> instance */ public static Comparator<Long> inverseLongComparator() { return INVERSE_LONG_COMPARATOR; } public static Comparator<Double> inverseDoubleComparator() { return INVERSE_DOUBLE_COMPARATOR; } /** * Instance assessor for the <code>Comparator</code> for Strings. This * is necessary because the String class did not implement * <code>Comparable</code> in Java 1.1.8. This is an instance because the * <code>StringComparator</code> has no state, allowing a single instance to be * used whenever a <code>Comparator</code> is needed for Strings. * * @return the <code>StringComparator</code> instance */ public static Comparator<String> stringComparator() { return STRING_COMPARATOR; } /** * Instance assessor for the <code>Comparator</code> for <code>File</code>s. This * is necessary because the <code>File</code> class did not implement * <code>Comparable</code> in Java 1.1.8. This is an instance because the * <code>FileComparator</code> has no state, allowing a single instance to be * used whenever a <code>Comparator</code> is needed for <code>File</code>s. * * @return the <code>FileComparator</code> instance */ public static Comparator<File> fileComparator() { return FILE_COMPARATOR; } /** * Instance assessor for the <code>Comparator</code> for case insensitive * <code>String</code>s. This is an instance because the * <code>CaseInsensitiveStringComparator</code> has no state, allowing a single * instance to be used whenever a <code>Comparator</code> is needed. * * @return the <code>CaseInsensitiveStringComparator</code> instance */ public static Comparator<String> caseInsensitiveStringComparator() { return CASE_INSENSITIVE_STRING_COMPARATOR; } /** * Compares two Integers. */ private static final class IntComparator implements Comparator<Integer>, Serializable { private static final long serialVersionUID = 830281396810831681L; public int compare(Integer o1, Integer o2) { return intCompareTo(o1, o2); } } /** * Compares two Integers the opposite way. */ private static final class InverseIntComparator implements Comparator<Integer> { public int compare(Integer o1, Integer o2) { return -intCompareTo(o1, o2); } } /** * Compares two <code>Long</code>s. Useful for storing Java * 1.1.8 <code>Long</code>s in Java 1.2+ sorted collections classes. This is * needed because <code>Long</code>s in 1.1.8 do not implement the * <code>Comparable</code> interface, unlike <code>Long</code>s in 1.2+. */ private static final class LongComparator implements Comparator<Long>, Serializable { private static final long serialVersionUID = 226428887996180051L; public int compare(Long o1, Long o2) { return longCompareTo(o1, o2); } } /** * Inverse comparison for two <code>Long</code>s. Useful for storing Java * 1.1.8 <code>Long</code>s in Java 1.2+ sorted collections classes. This is * needed because <code>Long</code>s in 1.1.8 do not implement the * <code>Comparable</code> interface, unlike <code>Long</code>s in 1.2+. */ private static final class InverseLongComparator implements Comparator<Long>, Serializable { private static final long serialVersionUID = 316426787496198051L; public int compare(Long o1, Long o2) { return -longCompareTo(o1, o2); } } /** * Compares <code>String</code> objects without regard to case. */ public static final class CaseInsensitiveStringComparator implements Comparator<String>, Serializable { private static final long serialVersionUID = 263123571237995212L; public int compare(String o1, String o2) { return o1.compareToIgnoreCase(o2); } } /** Compares two byte arrays. */ public static class ByteArrayComparator implements Comparator<byte[]> { public int compare(byte[] a, byte[] b) { for(int i = 0; i < a.length; i++) { if(a[i] > b[i]) return 1; else if(a[i] < b[i]) return -1; } return 0; } } /** * Compares two Integer objects numerically. This function is identical * to the Integer compareTo method. The Integer compareTo method * was added in Java 1.2, however, so any app that is 1.1.8 compatible * must use this method. */ public static int intCompareTo(Integer thisInt, Integer anotherInt) { return (thisInt < (int) anotherInt ? -1 : (thisInt == (int) anotherInt ? 0 : 1)); } /** * Compares two <code>Long</code> objects numerically. This function is * identical to the Long compareTo method. The Long compareTo method was * added in Java 1.2, however, so any app that is 1.1.8 compatible must use * this method. * * @param firstLong the first <code>Long</code> to be compared. * @param secondLong the second <code>Long</code> to be compared. * @return the value <code>0</code> if the first <code>Long</code> * argument is equal to the second <code>Long</code> argument; a value * less than <code>0</code> if the first <code>Long</code> argument is * numerically less than the second <code>Long</code>; and a * value greater than <code>0</code> if the first <code>Long</code> * argument is numerically greater than the second <code>Long</code> * argument (signed comparison). */ public static int longCompareTo(Long firstLong, Long secondLong) { return (firstLong < (long) secondLong ? -1 : (firstLong == (long) secondLong ? 0 : 1)); } }