Arrays类及其方法分析

排序

Arrays.sort()方法,对于基本数据类型采用DualPivotQuicksort(多路快排)进行排序,对于引用类型的数组,采用MergeSort(归并排序)进行排序,下面我们分别来讲一下这两类排序算法。

对基本类型数组的排序

Java中的八种基本数据类型,除了boolean,其它七种都是可以且有需求进行排序的,如果一个数组是单一的基础类型,形如int[] data, long data[]都可以直接使用Arrays.sort()进行排序。对于所有可排序的基本类型,都是采用DualPivotQuicksort来进行排序的。首先来看个例子:

package com.adam.java.algo.arrays;

import java.util.Arrays;

import org.junit.Test;

public class ArraysBasicTest {

@Test

public void testSortInteger() {

int data[] = { 10, 8, 9, 1, 2, 5, 98, 3, 7, 66 };

Arrays.sort(data);

for (int i : data) {

System.out.print(i + " ");

}

}

@Test

public void testSortChar() {

char data[] = { ‘D‘, ‘B‘, ‘E‘, ‘C‘, ‘H‘, ‘A‘, ‘Y‘, ‘G‘, ‘I‘, ‘O‘ };

Arrays.sort(data);

for (char i : data) {

System.out.print(i + " ");

}

}

}

输出:

1 2 3 5 7 8 9 10 66 98

A B C D E G H I O Y

这里我们要看一下Arrays.sort()采用的算法了,我们查看下JDK源码。

/**

  • Sorts the specified array into ascending numerical order.
  • <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
  • by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
  • offers O(n log(n)) performance on many data sets that cause other
  • quicksorts to degrade to quadratic performance, and is typically
  • faster than traditional (one-pivot) Quicksort implementations.
  • @param a the array to be sorted

*/

public static void sort(int[] a) {

DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);

}

发现所有的基本排序都是直接使用DualPivotQuicksort.sort()进行的,因此,我们有必要了解一下DualPivotQuicksort的原理。基本思想就是:

元素个数从1-47,则直接使用插入排序进行排序。

元素个数从47-286,则使用多路快速排序。

元素个数大于286,则使用归并排序

这里我们研究下多路快排的原理,首先我们回顾一下经典快排是怎么实现的。

经典快排实现思路:

  1. 找一个中轴,一般情况选取数组的第一个元素。
  2. 定义两个指针,分别指向最左边和最右边,从右边开始遍历,如果大于中轴,则右边指针左移一位,如果小于中轴,则互换位置;同理再从左边开始和中轴比较,如果小于中轴,指针向右移动,如果大于中轴,则互换位置。
  3. 一趟排序下来,中轴左边的都小于中轴,右边的都大于中轴。

4.递归的对子数组进行如上操作,不稳定,时间复杂度最优情况O(nlogn),最坏情况为基本有序时为O(n2)。关于快排的详细说明,请参考另一篇博文。

多路快排实现思路:

  1. 选取两个中轴P1, P2。
  2. 假设P1<P2,否则交换。
  3. 过程中原数组会分为四个部分:小于中轴1,大于中轴2,介于两个中轴之间,未排序部分(刚开始除了两个中轴,其它元素都属于这部分)。
  4. 开始后,从未排序部分选取一个数,和两个中轴作比较,然后放到合适的位置,一直到未排序部分无数据,结束一趟排序。
  5. 递归地处理子数组,稳定排序,时间复杂度稳定为O(nlogn)。

对引用类型的数组排序

我们举个例子,对User类型的数组,根据年龄进行排序,此处用到Comparator接口,更多关于Comparator的介绍,请点击。

新建一个User类:

package com.adam.java.algo.arrays;

public class User {

private String name;

private String gender;

private int age;

public User(String name, String gender, int age) {

this.name = name;

this.gender = gender;

this.age = age;

}

/**

  • @return the name

*/

public String getName() {

return name;

}

/**

  • @param name
  • the name to set

*/

public void setName(String name) {

this.name = name;

}

/**

  • @return the gender

*/

public String getGender() {

return gender;

}

/**

  • @param gender
  • the gender to set

*/

public void setGender(String gender) {

this.gender = gender;

}

/**

  • @return the age

*/

public int getAge() {

return age;

}

/**

  • @param age
  • the age to set

*/

public void setAge(int age) {

this.age = age;

}

}

再建一个排序类:

package com.adam.java.algo.arrays;

import java.util.Comparator;

public class UserComparator implements Comparator<User> {

@Override

public int compare(User o1, User o2) {

return o1.getAge() - o2.getAge();

}

}

测试:

package com.adam.java.algo.arrays;

import java.util.Arrays;

public class ArraysTest {

public static void main(String[] args) {

User[] users = new User[]{new User("egg", "male", 26), new User("Kity", "Female", 25), new User("Pole", "male", 23), new User("Jack", "male", 28)};

Arrays.sort(users, new UserComparator());

for (User user : users) {

System.out.println("name: " + user.getName() + " ,age: "+user.getAge());

}

}

}

输出:

name: Pole ,age: 23

name: Kity ,age: 25

name: egg ,age: 26

name: Jack ,age: 28

这就是一个简单的对引用类型的数组排序的例子,在JDK1.8中,对引用类型的排序,采用的归并排序的算法。

在JDK1.8中,对于排序方法,还引入了parallelSort(),每个sort()都有对应的并行排序方法,当数组元素个数大于2的13次(8196)后采用parallelSort()。

搜索

在用二分搜索对一个已经有序的数组进行查找,如果存在,返回key在该数组中的位置,如果不存在,返回负数,值为:-插入点-1,举个例子:

假设一个排好序的数组是:1,6,8,10,12,如果key为7,则返回值为-3,因为7应该插入到6,8之间,所以插入点为2(下标从0开始),所以返回值为-2-1=-3。

ArrayToList

这方面,是将一个数组,转换成一个list形式,注意:通常情况下,如果该数组是int型的,如int[[ data,这种情况会出现并不是直接将该数组中的所有元素转成新的list的所有元素,而是将整个数组,转成list的一个元素,这是一种特殊情况,将类型int改成Integer就可以避免了。此处感谢网友@Java我人生指正!

/**

  • Returns a fixed-size list backed by the specified array. (Changes to
  • the returned list "write through" to the array.) This method acts
  • as bridge between array-based and collection-based APIs, in
  • combination with {@link Collection#toArray}. The returned list is
  • serializable and implements {@link RandomAccess}.
  • <p>This method also provides a convenient way to create a fixed-size
  • list initialized to contain several elements:
  • <pre>
  • List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
  • </pre>
  • @param <T> the class of the objects in the array
  • @param a the array by which the list will be backed
  • @return a list view of the specified array

*/

@SafeVarargs

@SuppressWarnings("varargs")

public static <T> List<T> asList(T... a) {

return new ArrayList<>(a);

}

根据注释得知,返回的新list是个定长的list,而且并不可以就行添加或者删除元素,否则报:java.lang.UnsupportedOperationException异常。这是为什么?因为此处的ArrayList并非我们常用的java.util.ArrayList类,而是Arrays类的一个内部类,因为继承了AbstractList,所有可以和list相互转换,但是不具备add和remove等操作。

CopyOf

Arrays.copyOf()用来进行数组的复制,返回一个全新的数组,可以传入一个参数来定义新数组的大小,如果传入的数小于原来的数组长度,则直接把原数组多余的部分剪掉,如果传入的值大于原数组,则新数组多余的部分补默认值(对于int类型的,补0)。

原文地址:https://blog.51cto.com/14226273/2364862

时间: 2024-10-15 12:30:26

Arrays类及其方法分析的相关文章

Java之美[从菜鸟到高手演练]之Arrays类及其方法分析

作者:二青 个人站点:zhangerqing.cn    邮箱:[email protected]    微博:http://weibo.com/xtfggef 本章主要介绍一下 java.util.Arrays类的重点方法,包括怎么使用及实现原理.这是一个算法类,主要是辅助数组类实现一些排序.搜索等功能,同时也支持数组到List的转换.本章系Java之美[从菜鸟到高手演练]系列之Arrays类及其方法分析,如果有任何问题,欢迎通过上面任何一种方式与我联系! 排序 本文使用JDK1.8.0_25

JAVA数组之Arrays类及其方法

public class Arraysextends Object此类包含用来操作数组(比如排序和搜索)的各种方法.此类还包含一个允许将数组作为列表来查看的静态工厂. 除非特别注明,否则如果指定数组引用为 null,则此类中的方法都会抛出 NullPointerException. 此类中所含方法的文档都包括对实现 的简短描述.应该将这些描述视为实现注意事项,而不应将它们视为规范 的一部分.实现者应该可以随意替代其他算法,只要遵循规范本身即可.(例如,sort(Object[]) 使用的算法不必

Arrays类的分析及使用

1.  Arrays类介绍 Arrays类是Java API中提供的类,在java.util包中,此类包含用来操作数组的各种方法,比如排序和搜索,在这个类中如果指定数组引用为null,则此类方法都会抛出NullPointerException,此类还包含一个允许将数组作为列表来查看的静态工厂. Arrays类包含sort,binarySearch,equals,fill,copyOf,asList,hashCode,deepHashCode,deepEquals,toString和deepToS

7.Java集合-Arrays类实现原理及源码分析

Java集合---Arrays类源码解析 转自:http://www.cnblogs.com/ITtangtang/p/3948765.html 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类型:采用改进的归并排序. 1.对于基本类型源码分析如下(以int[]为例): Java对Primitive(int,float等原型数据)数组采用快速排序,对

NSMutableDictionary 类中增加键值对方法分析

在iOS中可变字典增加一个键值对的方法有setObject: forKey: 和setValue : forKey: .为了方便我们把这两个方法简称为方法A和方法B. B这个方法中其中的value值是不能为nil,否则程序会出项崩溃.而A方法中的这个value可以为nil,但是当这个value位nil时,系统会自动调用removeObjectforKey:这个方法.这样就把这个键值对删除掉了.B方法中的key值可以是任意类型的,但是这个类型必须要实现NSCopying协议.而A方法中它的key值

Arrays 类的 binarySearch() 数组查询方法详解

Arrays类的binarySearch()方法,可以使用二分搜索法来搜索指定的数组,以获得指定对象.该方法返回要搜索元素的索引值.binarySearch()方法提供多种重载形式,用于满足各种类型数组的查找需要. 注意:使用 binarySearch() 方法前,必须先用 Arrays.sort() 方法排序,否则结果可能是非预期值 1)  binarySearch(Object[], Object key) a: 要搜索的数组 key:要搜索的值 如果key在数组中,则返回搜索值的索引:否则

Java中Arrays类的两个方法:deepEquals和equals

deepEquals和equals是Java中Arrays类的两个静态方法,可是它们之间有什么样的区别呢? 代码一. import java.util.Arrays; public class Test { public static void main(String[] args) { String[][] name1 = {{ "G","a","o" },{ "H","u","a",

Google Test(GTest)使用方法和源码解析——模板类测试技术分析和应用

写C++难免会遇到模板问题,如果要针对一个模板类进行测试,似乎之前博文中介绍的方式只能傻乎乎的一个一个特化类型后再进行测试.其实GTest提供了两种测试模板类的方法,本文我们将介绍方法的使用,并分析其实现原理.(转载请指明出于breaksoftware的csdn博客) 应用 GTest将这两种方法叫做:Typed Tests和Type-Parameterized Tests.我觉得可能叫做简单模式.高级模式比较通用.先不管这些名字吧,我们看看怎么使用 简单模式(Typed Tests) 首先我们

Collections 工具类和 Arrays 工具类常见方法

Collections 工具类和 Arrays 工具类常见方法 Collections Collections 工具类常用方法: 排序 查找,替换操作 同步控制(不推荐,需要线程安全的集合类型时请考虑使用 JUC 包下的并发集合) 排序操作 void reverse(List list)//反转 void shuffle(List list)//随机排序 void sort(List list)//按自然排序的升序排序 void sort(List list, Comparator c)//定制