一 字符串数组的排序
常见的排序是数字型数组的排序,有冒泡法,快速排序法,插入法等。 字符串数组也可以进行相应的排序,只是字符串之间的比较并不是通过 > < 来进行体现的。 字符串提供了一个方法,叫做 compareTo() 的方法,是利用字典顺序进行相应的比较。这里,字符串数组的排序所用的方法是 简单的冒泡排序法。
二. compareTo() 方法的使用比较
字符,数字 之间的比较
@Test public void testA(){ System.out.println("abc".compareTo("acd")); //返回-1 b小于c,前面的小于后面的 System.out.println("abc".compareTo("aef")); //返回-3 b小于e,中间相差3个值,e-b=3 System.out.println("acd".compareTo("abc")); //1 c大于b System.out.println("aef".compareTo("abc")); //3 System.out.println("acd".compareTo("123")); // 48 为97-49=48 字符串大于数字 System.out.println("123".compareTo("acd")); // -48 System.out.println("acd".compareTo("acd1234")); // -4 返回的是相差的长度 }
实际上,比较的是ASCII 码的大小,返回的值也是最近那两个字符不同的差值,如果相同返回0. 但返回值并不是以前常见的 -1, 1, 0.
三. 源代码的分析
public int compareTo(String anotherString) { // 当前字符串的长度 int len1 = value.length; // 要比较的字符串的长度 int len2 = anotherString.value.length; // 求出最小的字符串的长度 int lim = Math.min(len1, len2); // 当前字符串转换成字符数组,相当于 toCharArray(); char v1[] = value; // 要比较的字符串转换成字符数组 char v2[] = anotherString.value; int k = 0; while (k < lim) { //用while 循环 // 当前的字符串的那个字符值 char c1 = v1[k]; // 要比较的字符串的那个字符值 char c2 = v2[k]; // 不同时,返回 ASCII 码的差值。 if (c1 != c2) { return c1 - c2; } k++; } // 前面的全部相同,那么则返回两个字符串的长度的差值。 // 全部相同,用的也是len1-len2,即全部相同时,长度也一定相同,返回长度差值0. return len1 - len2; }
String 中还有一个 CaseInsensitiveComparator 的比较器,
public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator(); private static class CaseInsensitiveComparator implements Comparator<String>, java.io.Serializable { }
但是这个比较器,只是用来比较忽略大小写的。 即比较时,忽略大小写。
public int compareToIgnoreCase(String str) { return CASE_INSENSITIVE_ORDER.compare(this, str); }
所调用的compare() 方法是:
public int compare(String s1, String s2) { int n1 = s1.length(); int n2 = s2.length(); // 取出最小的长度 int min = Math.min(n1, n2); for (int i = 0; i < min; i++) { //得到i 索引的值 char c1 = s1.charAt(i); char c2 = s2.charAt(i); //看两个字符的ASCII 码是否相同 if (c1 != c2) { // 不相同,转换成大写字符 c1 = Character.toUpperCase(c1); c2 = Character.toUpperCase(c2); // 如果大写字符不相同,就转换成小写字符 if (c1 != c2) { c1 = Character.toLowerCase(c1); c2 = Character.toLowerCase(c2); // 小写字符不相同,就返回小写字符的ASCII 码。 if (c1 != c2) { // No overflow because of numeric promotion return c1 - c2; } } } } // 返回长度的差值。 return n1 - n2; }
这样的写法,感觉有点多余,直接都转换成大写,进行判断不行吗? 为什么要转换成大写之后,再转换成小写呢? 感觉没有 compareTo () 方法写得简单。 也许,底层人员是提示不同的解决方法吧。 注意,忽略大小写的比较,是用的一个比较器,并不是单纯的对字符串的处理后比较。
测试:
@Test public void testB(){ System.out.println("abc".compareToIgnoreCase("ABC")); //0 System.out.println("abc".compareToIgnoreCase("Abc")); //0 System.out.println("abc".compareToIgnoreCase("AbC")); //0 }
四. 字符串数组排序
public static void main(String []args){ String[] arr=new String[]{"abc","aed","afg","cdeg","acd"}; System.out.println("排序前:"); print(arr); compareArr(arr); System.out.println("排序后:"); print(arr); } private static void compareArr(String[] arr) { //利用冒泡排序法进行相关的排序 for (int i = 0; i < arr.length; i++) { for(int j=0;j<arr.length-1-i;j++){ // 比较方式是> 0 <0 这样的比较。 if(arr[j].compareTo(arr[j+1])>0){ // 数组元素间进行调换 swapArr(arr,j,j+1); } } } } // 调换数组元素的值 private static void swapArr(String []arr,int start,int end){ String temp=arr[start]; arr[start]=arr[end]; arr[end]=temp; } // 打印输出数组 private static void print(String []arr){ System.out.println(Arrays.toString(arr)); }
谢谢!!!