/* * @(#)CharSequenceComparator.java 7/15/2008 * * Copyright 2002 - 2008 JIDE Software Inc. All rights reserved. * */ package com.jidesoft.comparator; import java.io.Serializable; import java.util.Comparator; /** * A Comparator that compares CharSequence objects (including String and StringBuffer as both extend CharSequence. * Throws ClassCastExceptions if the objects are not CharSequence, or if they are null. If both objects are null, they * will be treated as equal. If one is null and the other is not, the null value will be treated as smaller then * non-null value. */ public class CharSequenceComparator implements Comparator<Object>, Serializable { private static final long serialVersionUID = -4749963150099170895L; private boolean _caseSensitive; public static final ComparatorContext CONTEXT = new ComparatorContext("IgnoreLocale"); public static final ComparatorContext CONTEXT_IGNORE_CASE = new ComparatorContext("IgnoreLocale_Ignorecase"); /** * Constructs a CharSequenceComparator. */ public CharSequenceComparator() { this(true); } public CharSequenceComparator(boolean caseSensitive) { _caseSensitive = caseSensitive; } /** * Checks if the case is sensitive when comparing. * * @return true if the comparator is case sensitive. */ public boolean isCaseSensitive() { return _caseSensitive; } /** * Sets the case sensitive flag. By default, it's true meaning the comparator is case sensitive. * * @param caseSensitive true or false. */ public void setCaseSensitive(boolean caseSensitive) { _caseSensitive = caseSensitive; } public int compare(Object o1, Object o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { return -1; } else if (o2 == null) { return 1; } if (o1 instanceof CharSequence) { if (o2 instanceof CharSequence) { CharSequence s1 = (CharSequence) o1; CharSequence s2 = (CharSequence) o2; return isCaseSensitive() ? compareCase(s1, s2) : compareIgnoreCase(s1, s2); } else { // o2 wasn't comparable throw new ClassCastException("The second argument of this method was not a CharSequence: " + o2.getClass().getName()); } } else if (o2 instanceof Comparable) { // o1 wasn't comparable throw new ClassCastException("The first argument of this method was not a CharSequence: " + o1.getClass().getName()); } else { // neither were comparable throw new ClassCastException("Both arguments of this method were not CharSequences: " + o1.getClass().getName() + " and " + o2.getClass().getName()); } } private int compareCase(CharSequence s1, CharSequence s2) { int len1 = s1.length(); int len2 = s2.length(); int n = Math.min(len1, len2); int k = 0; while (k < n) { char c1 = s1.charAt(k); char c2 = s2.charAt(k); if (c1 != c2) { return c1 - c2; } k++; } return len1 - len2; } private int compareIgnoreCase(CharSequence s1, CharSequence s2) { int n1 = s1.length(), n2 = s2.length(); for (int i1 = 0, i2 = 0; i1 < n1 && i2 < n2; i1++, i2++) { char c1 = s1.charAt(i1); char c2 = s2.charAt(i2); if (c1 != c2) { c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); if (c1 != c2) { return c1 - c2; } } } } return n1 - n2; } // /** // * * sort a set of string from stdin // */ // public static void main(String[] args) { // try { // Vector<String> v = new Vector<String>(); // for (int i = 0; i < 1; i++) { // v.add("a1"); // v.add("A2"); // v.add("a2"); // v.add("a10"); // v.add("a1c1"); // v.add("a1c2"); // v.add("a1c10"); // v.add("a1c20"); // v.add("a100"); // v.add("b3"); // v.add("c3"); // v.add("cc3"); // v.add("cc2"); // v.add("1.doc"); // v.add("2.doc"); // v.add("3.doc"); // v.add("4.doc"); // v.add("5.doc"); // v.add("6.doc"); // v.add("7.doc"); // v.add("8.doc"); // v.add("9.doc"); // v.add("10.doc"); // v.add("11.doc"); // v.add("12.doc"); // v.add("13.doc"); // v.add("14.doc"); // v.add("15.doc"); // v.add("16.doc"); // v.add("17.doc"); // v.add("18.doc"); // v.add("19.doc"); // v.add("20.doc"); // v.add("100.doc"); // v.add("101.doc"); // v.add("102.doc"); // } // long start = System.nanoTime(); // Collections.sort(v, new CharSequenceComparator()); // long end = System.nanoTime(); // System.out.println(end - start); // for (String s : v) System.out.println(s); // } // catch (Throwable error) { // error.printStackTrace(); // System.exit(-1); // } // } }