`
jiangshuiy
  • 浏览: 336227 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java类库中Arrays的排序算法探析(Object与泛型类型)

阅读更多

     在Arrays中关于基本类型如int,long,float等都在java类库中Arrays的排序算法探析(基础类型)做了一定分析,本篇主要关于Object类型的sort,以及之后的泛型sort。

 

直接查看源码中的方法定义及实现:

 

    public static void sort(Object[] a) {
        Object[] aux = (Object[])a.clone();
        mergeSort(aux, a, 0, a.length, 0);
    }


    public static void sort(Object[] a, int fromIndex, int toIndex) {
        rangeCheck(a.length, fromIndex, toIndex);//验证参数是否合法
	Object[] aux = copyOfRange(a, fromIndex, toIndex);//创建待排序数组临时存储区
        mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
    }

 

由上可见,两个重载方法的具体实现指向了同一个具体实现,应该是个私有方法:

 

/**
     * Src is the source array that starts at index 0
     * Dest is the (possibly larger) array destination with a possible offset
     * low is the index in dest to start sorting
     * high is the end index in dest to end sorting
     * off is the offset to generate corresponding low, high in src
     */
    private static void mergeSort(Object[] src,
				  Object[] dest,
				  int low,
				  int high,
				  int off) {
	int length = high - low;

	// Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
			 ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
 

        当然,如果能直接看代码一眼就完全明白的话,那到此就可以为止了。

先理一下流程:

1 如果待排序的数组大小小于设置的插入排序阈值,则直接采用插入排序解决;

2 如果不满足1,则将其一分为二,递归处理;这样经过多次递归,其实最终还是分段采用插入排序将其拆分为了N个有序的段;

3 到了这里,前面是多个分别有序的段,这里需要将其逐一连接起来,使其更大长度上有序,这一部分展示的就是:如果前一段的最后一个值(也就是前一段的最大值)小于紧挨着的后一个段的第一个值(也就是这一段的最小值),则这两段总体是有序的;

4 如果没有3那种理想状态,则需要我们来处理,这里处理的思想就是:前后两段逐一开始比较,小的先放,依次放第二小的,直到两段都为空;

5 3或4逐级返回,最终构成一个整体的有序数组。

 

再说泛型的排序:

 

 public static <T> void sort(T[] a, Comparator<? super T> c) {
	T[] aux = (T[])a.clone();
        if (c==null)
            mergeSort(aux, a, 0, a.length, 0);
        else
            mergeSort(aux, a, 0, a.length, 0, c);
    }

public static <T> void sort(T[] a, int fromIndex, int toIndex,
				Comparator<? super T> c) {
        rangeCheck(a.length, fromIndex, toIndex);
	T[] aux = (T[])copyOfRange(a, fromIndex, toIndex);
        if (c==null)
            mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
        else
            mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
    }

 可以看出来,泛型排序的处理过程几乎和对象数组的一模一样,值得注意的是,如果Comparator为null,则使用默认的Comparable接口的自然序。下面看具体调用的实现方法:

 

private static void mergeSort(Object[] src,
				  Object[] dest,
				  int low, int high, int off,
				  Comparator c) {
	int length = high - low;

	// Insertion sort on smallest arrays
	if (length < INSERTIONSORT_THRESHOLD) {
	    for (int i=low; i<high; i++)
		for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
		    swap(dest, j, j-1);
	    return;
	}

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }

 仔细看来,无Comparator的实现和对象数组的事项没有任何差别,具有Comparator的也仅仅在比较使采取的是compare方法来决定数组顺序。

 

这个实现值得学习的有几点:

1 小规模的比较采取的是插入排序,这就避免了递归到一个数组只有一个元素那种情况,在小规模情况下,插入排序实现简单,效率也还可以(类库中设置的是7);

2 在相邻两段的连接时,如果发现两个段的连接处构成正确顺序,则直接返回,减少了需要逐个比较元素重新插入一遍带来的性能影响;

3 无符号位运算取中间值,代替/;

4 对外接口与对内实现的独立,对外可能有多个接口,但内部实现其实是一样的,这样非常方便于后续调整和性能优化;

总体感觉就是这些方法的实现极大的优化了性能,并且给后续调整留下了空间,便于维护。

 

唯一感到有点不足的就是:

就是临时变量实在是有点多,刚开始难以理解~

 

 

分享到:
评论

相关推荐

    Java排序算法实现:冒泡与选择排序示例代码

    这个资源是关于Java中排序算法实现的简单示例。排序算法是计算机科学中的基础概念,用于按升序或降序排列数据集。这里提供了两种常见的排序算法实现:冒泡排序和选择排序。 冒泡排序(Bubble Sort) 是一种基本的...

    031112_【第11章:Java常用类库】_Arrays笔记

    031112_【第11章:Java常用类库】_Arrays笔记

    Json-lib 是一个 Java 类库

    •转换 javabeans, maps, collections, java arrays 和 XML 成为 json 格式数据 •转换 json 格式数据成为 javabeans 对象 Json-lib 需要的 jar 包 •commons-beanutils-1.8.3.jar •commons-collections-3.2.1.jar...

    九种内部排序算法,Java版

    ## 九种内部排序算法的Java实现及其性能测试 ### 9种内部排序算法性能比较 第九种为java.util.Arrays.sort(改进的快速排序方法) 1. 100000的随机数据集 ![](http://7xlkoc.com1.z0.glb.clouddn.com/sort1.jpg) ...

    Java编程实现中英混合字符串数组按首字母排序的方法

    在Java中对于字符串数组的排序,我们可以使用Arrays.sort(String[])方法很便捷的进行排序。例如: String[] arrays = new String[] { gyu, sdf, zf, 大同, 收到, 地方, 三等分, 的人, 反对高铁, 泛代数, 上的投入...

    Java期末复习-常用类库

    Java期末复习-常用类库 StringBuffer、Runtime、国际化程序、System、日期操作类、Math、Random、NumberFormat、BigInteger、BigDecimal、对象克隆技术、Arrays、Comparable、正则表达式、定时调度

    冒泡排序 算法(冒泡,选择,插入,数组排序)

    算法(冒泡,选择,插入,数组排序) package Teacher; import java.io.*; import java.util.Scanner; public class Tset { public static void main(String args[]) throws IOException { // 需要排序的数组,...

    几种排序算法的比较(java代码)

    String[] strs2=new String[]{"希尔排序","直接插入排序","折半插入排序","冒泡排序"}; new SortTest().test(strs2,100000,1900000,100000); } private void testErr(String[] strings) throws Exception{...

    java的arrays数组排序示例分享

    排序算法,基本的高级语言都有一些提供。C语言有qsort()函数,C++有sort()函数,java语言有Arrays类(不是Array)。用这些排序时,都可以写自己的排序规则

    Java数组高级算法与Arrays类常见操作小结【排序、查找】

    主要介绍了Java数组高级算法与Arrays类常见操作,结合实例形式总结分析了Java数组常见的排序算法、查找算法相关原理、实现与使用技巧,需要的朋友可以参考下

    冒泡、选择、插入、快速、arrays排序排序.txt

    含有冒泡、选择、插入、快速、arrays排序

    我是如何击败Java自带排序算法的

    对于整形和其他的基本类型, Arrays.sort() 综合利用了双枢轴快速排序、归并排序和启发式插入排序。这个算法是很强大的,可以在很多情况下通用。针对大规模的数组还支持更多变种。我拿自己仓促写的排序算法跟Java...

    Java Methods-Arrays.ppt

    Java Methods-Arrays.ppt

    Java中Arrays实用方法

    /** *Arrays提供数组操作的一系列实用方法 *1输出 *2排序 *3二分查找 *4复制 *5扩容 */

    Java股票分析排序

    现有股票数据XX条,无序...注意:实现排序算法可以使用冒泡排序,插入排序,堆排序,选择排序,快速排序等,任何的排序算法都是可以被接受的,但不能使用系统库中自带的排序函数,如List.sort() 或者 Arrays.sort()。

    Java, Java, Java, Object-Oriented Problem Solving (3rd Edition)

    Java, Java, Java, Object-Oriented Problem Solving (3rd Edition) 3rd Edition by Ralph Morelli (Author), Ralph Walde (Author) 856 pages (June 25, 2017) 出版社: Prentice Hall; 3 edition Language: ...

    java泛型总结.docx

    泛型类型:定义泛型类型时,使用尖括号,并在尖括号中指定类型参数。例如,List表示一个字符串类型的列表。 泛型方法:定义泛型方法时,在方法名后面使用尖括号,并在尖括号中指定类型参数。例如,public static &lt;T&gt;...

    Java中Arrays类详解.docx

    java arrays类

    SortingSounds:可视化三种不同排序算法的Java应用程序

    可视化三种不同排序算法的Java应用程序:冒泡排序,快速排序和数组排序,可以选择对排序时进行的每个比较播放不同的音调。 该应用程序包含4个控件和一个按钮,用于开始可视化。 排序方法ChoiceBox允许在不同的排序...

    Toward Long Distance, Sub-diffraction Imaging Using Coherent Camera Arrays 论文算法

    Toward Long Distance, Sub-diffraction Imaging Using Coherent Camera Arrays一文中的算法,采用Fourier ptychographic imaging原理,用多幅低分辨率图像重建高分辨率的图像

Global site tag (gtag.js) - Google Analytics