关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JAVA »Java ArrayList 的不同排序方法

    Java ArrayList 的不同排序方法

    2015-12-13 00:00:00 出处:ImportNew
    分享

    微信扫一扫:分享

    Scan me!

    微信里点“发现”,扫一下

    二维码便可将本文分享至朋友圈。

    由于其功能性和灵活性,ArrayList是 Java 集合框架中使用最为普遍的集合类之一。ArrayList 是一种 List 实现,它的内部用一个动态数组来存储元素,因此 ArrayList 能够在添加和移除元素的时候进行动态的扩展和缩减。你可能已经使用过 ArrayList,因此我将略过基础部分。如果你对 ArrayList 还不熟悉,你可以参考它的 API 文档,可以很容易理解在 ArrayList 上执行基本的操作。

    在这篇文章中,我将讨论 ArrayList 中一种极其重要的操作,你很有可能需要在企业应用开发中实现它。它就是 ArrayList 元素的排序。

    排序字符串对象的 ArrayList

    考虑一个 ArrayList 存储着以字符串形式存在的国名(country name),为了对这个 ArrayList 进行排序,你需要调用 Collections.sort()方法,传递由国名构成的 ArrayList 对象。这种方法将按照自然顺序(按字母升序)对元素(国名)进行排序。让我们为此来写一段代码。

    SortArrayListAscendingDescending.java

    package guru.springframework.blog.sortarraylist.ascendingdescending;
     import java.util.ArrayList;
     import java.util.Collections;
     public class SortArrayListAscendingDescending {
     private ArrayList arrayList;
     public SortArrayListAscendingDescending(ArrayList arrayList) {
     this.arrayList = arrayList;
     }
     public ArrayList getArrayList() {
     return this.arrayList;
     }
     public ArrayList sortAscending() {
     Collections.sort(this.arrayList);
     return this.arrayList;
     }
     public ArrayList sortDescending() {
     Collections.sort(this.arrayList, Collections.reverseOrder());
     return this.arrayList;
     }
     }

    在上面的类中,我们在构造器中初始化了一个 ArrayList 对象。在 sortAscending()方法中,我们调用了 Collections.sort()方法,并传递这个初始化的 ArrayList对象为参数,返回排序后的 ArrayList。在 sortDescending()方法中,我们调用重载的 Collections.sort()方法让其按照降序对元素排序,这个版本的 Collections.sort()接收ArrayList对象作为第一个参数,一个由 Collections.reverseOrder()方法返回的 Comparator 对象作为第二个参数。我们将会在稍后讲解 Comparator。为了测试排序功能,我们将写一段测试代码。

    SortArrayListAscendingDescendingTest.java

    package guru.springframework.blog.sortarraylist.ascendingdescending;
     import org.junit.Test;
     import java.util.ArrayList;
     import static org.junit.Assert.*;
     public class SortArrayListAscendingDescendingTest {
     <a href="http://www.jobbole.com/members/madao">@Test</a>
     public void testSortAscendingDescending() throws Exception {
     ArrayList countryList = new ArrayList&lt;&gt;();
     countryList.add("France");
     countryList.add("USA");
     countryList.add("India");
     countryList.add("Spain");
     countryList.add("England");
     SortArrayListAscendingDescending sortArrayList = new SortArrayListAscendingDescending(countryList);
     ArrayList unsortedArrayList = sortArrayList.getArrayList();
     System.out.println("Unsorted ArrayList: " + unsortedArrayList);
     ArrayList sortedArrayListAscending = sortArrayList.sortAscending();
     System.out.println("Sorted ArrayList in Ascending Order : " + sortedArrayListAscending);
     ArrayList sortedArrayListDescending = sortArrayList.sortDescending();
     System.out.println("Sorted ArrayList in Descending Order: " + sortedArrayListDescending);
     }
     }

    在上面的测试代码中,我们创建一个 ArrayList 对象,并添加了 5 个字符串对象代表 5 个国家的名字。然后我们调用 getArrayList()、sortAscending()和 sortDescending()方法,并打印这些方法返回的 ArrayList 对象。

    输出如下:

    ------------------------------------------------------- 
    T E S T S 
    -------------------------------------------------------   
    Running guru.springframework.blog.sortarraylist.ascendingdescending.SortArrayListAscendingDescendingTest   
    Unsorted ArrayList: [France, USA, India, Spain, England] 
    Sorted ArrayList in Ascending Order : [England, France, India, Spain, USA] 
    Sorted ArrayList in Descending Order: [USA, Spain, India, France, England]   
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in guru.springframework.blog.sortarraylis

    到目前为止,所要排序的 ArrayList 元素都是非常简单的,我们仅仅只是调用 Collections.sort()方法并传递了需要排序的 ArrayList 对象作为参数。但是更多的是你会遇到一些复杂的情景下对 ArrayList 进行排序。

    Collections.sort() 方法对 ArrayList 的元素或者任何其他 List 的实现提供的可比较的元素进行排序,这意味着这些元素的类需要实现 java.lang 包中的 Comparable 接口。正如 String 类实现了 Comparable 接口,我们就可以对由国名构成的 ArrayList 排序。有些其他的标准 Java 类实现了 Comparable 接口,包括原始的包装类,例如 Integer、Short、Double、Float、Boolean、BigInteger、BigDecimal、File 和 Date 类都实现了 Comparable 接口。

    使用Comparable排序ArrayList

    Comparable 是带有单一?compareTo()方法的接口。一个实现了 Comparable 接口的类对象可以与其它同类型的对象进行比较,实现 Comparable 接口的类需要重写 compareTo()方法,这个方法接收一个同类型的对象,并实现这个对象和传递给方法的另一个对象比较的逻辑。compareTo()方法返回Int类型的比较结果,分别代表下面的含义:

    正值表示当前对象比传递给 comPareTO()的对象大 负值表示当前对象比传递给 comPareTO()的对象小 零表示两个对象相等

    让我们来举一个例子,JobCandidate 类的对象保存在 ArrayList 中并准备对其进行排序。JobCandidate 类有三个成员变量:字符串类型的姓名和性别、整型的年龄。我们想要对保存在 ArrayList 中的 JobCandidate 对象按照年龄进行排序。因此我们要让 JobCandidate 类实现 Comparable 接口并重写 compareTo()方法。

    JobCandidate类的代码如下:

    JobCandidate.java

    package guru.springframework.blog.sortarraylist.comparable;
     public class JobCandidate implements Comparable {
     private String name;
     private String gender;
     private int age;
     public JobCandidate(String name, String gender, int age) {
     this.name = name;
     this.gender = gender;
     this.age = age;
     }
     public String getName() {
     return name;
     }
     public String getGender() {
     return gender;
     }
     public int getAge() {
     return age;
     }
     @Override
     public int compareTo(JobCandidate candidate) {
     return (this.getAge() < candidate.getAge() ? -1 :
     (this.getAge() == candidate.getAge() ? 0 : 1));
     }
     @Override
     public String toString() {
     return " Name: " + this.name + ", Gender: " + this.gender + ", age:" + this.age;
     }
     }

    在上面 JobCandidate 类被重写的 compareTo()方法中,我们实现了基于年龄的比较逻辑。我见过很多程序员将(this.getAge() – candidate.getAge())作为返回的比较结果。尽管使用这种 return 语句看上去似乎很吸引人,并且也不会对我们的例子造成影响,我的建议是远离这种语句。想象一下,比较整数值,其中有一个或者两个都是负数的结果。这会导致一些错误,让你的程序行为不定,而且更重要的是,这样的错误是很细微的,尤其是在大型的企业应用中很难检测出来。下面我们将写一个辅助类,为委托方对包含了 JobCandidate 元素的 ArrayList 对象进行排序。

    JobCandidateSorter.java

    package guru.springframework.blog.sortarraylist.comparable;
    import java.util.ArrayList;
     import java.util.Collections;
     public class JobCandidateSorter {
     ArrayList jobCandidate = new ArrayList<>();
     public JobCandidateSorter(ArrayList jobCandidate) {
     this.jobCandidate = jobCandidate;
     }
     public ArrayList getSortedJobCandidateByAge() {
     Collections.sort(jobCandidate);
     return jobCandidate;
     }
     }

    在 JobCandidateSorter 类中,我们初始化了一个 ArrayList 对象,委托方将通过构造函数实例化 JobCandidateSorter 。然后我们编写了 getSortedJobCandidateByAge()方法,在这个方法中,我们调用 Collections.sort()并传递已经初始化了的 ArrayList 为参数,最后返回排序后的 ArrayList。

    接下来,我们写一个测试类来测试一下我们的代码。

    JobCandidateSorterTest.java

    package guru.springframework.blog.sortarraylist.comparable;
     import org.junit.Test;
     import java.lang.reflect.Array;
     import java.util.ArrayList;
     import static org.junit.Assert.*;
     public class JobCandidateSorterTest {
     <a href="http://www.jobbole.com/members/madao">@Test</a>
     public void testGetSortedJobCandidateByAge() throws Exception {
     JobCandidate jobCandidate1 = new JobCandidate("Mark Smith", "Male", 26);
     JobCandidate jobCandidate2 = new JobCandidate("Sandy Hunt", "Female", 23);
     JobCandidate jobCandidate3 = new JobCandidate("Betty Clark", "Female", 20);
     JobCandidate jobCandidate4 = new JobCandidate("Andrew Styne", "Male", 24);
     ArrayList jobCandidateList = new ArrayList&lt;&gt;();
     jobCandidateList.add(jobCandidate1);
     jobCandidateList.add(jobCandidate2);
     jobCandidateList.add(jobCandidate3);
     jobCandidateList.add(jobCandidate4);
     JobCandidateSorter jobCandidateSorter = new JobCandidateSorter(jobCandidateList);
     ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByAge();
     System.out.println("-----Sorted JobCandidate by age: Ascending-----");
    for (JobCandidate jobCandidate : sortedJobCandidate) {
     System.out.println(jobCandidate);
     }
     }
     }

    在上面的测试类中,我们创建了四个 JobCandidate 对象并把它们添加到 ArrayList,然后传递这个 ArrayList 到构造函数来实例化 JobCandidateSorter 类。最后,我们调用 JobCandidateSorter 类的 getSortedJobCandidateByAge()方法,并打印这个方法返回的排序后的 ArrayList。测试的输出结果如下:

    ------------------------------------------------------- 
    T E S T S 
    ------------------------------------------------------- 
    Running guru.springframework.blog.sortarraylist.comparable.JobCandidateSorterTest 
    -----Sorted JobCandidate by age: Ascending----- 
    Name: Betty Clark, Gender: Female, age:20 
    Name: Sandy Hunt, Gender: Female, age:23 
    Name: Andrew Styne, Gender: Male, age:24 
    Name: Mark Smith, Gender: Male, age:26 
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.003 sec 
    - in guru.springframework.blog.sortarraylist.comparable.JobCandidateSorterTest

    使用 Comparable 对 ArrayList 排序是一种常用的方法。但是你必须知道有某些限制。你想要排序的对象的类必须实现 Comparable 并覆写 compareTo()方法。这基本上意味着你将只能基于一个成员变量来比较对象(我们例子中的年龄字段)。如果要求你按照姓名和年龄来对 JobCandidate 对象进行排序怎么办? Comparable 就不是解决的方法了。另外,比较逻辑是需要进行比较的对象的类的一部分,它消除了比较逻辑可复用性的可能。Java 通过使用在 java.util 包下提供的Comparator接口解决了上述的比较需求。

    使用 Comparator 排序 ArrayList

    Comparator 接口与Comparable 接口相似也提供了一个单一的比较方法叫作 compare()。然而,与 Comparable的 compareTo()方法不同的是,这个 compare()接受两个同类型的不同对象进行比较。

    我们将用 Comparator 对我们之前使用过的相同?JobCandidate 类对象进行排序。我们将通过实现 Comparatoras 匿名内部类,允许对 JobCandidate 对象按照年龄和姓名进行排序。

    下面是使用了 Comparator 的 JobCandidate 类代码

    JobCandidate.java

    package guru.springframework.blog.sortarraylist.comparator;
     import java.util.Comparator;
     public class JobCandidate {
     private String name;
     private String gender;
     private int age;
     public JobCandidate(String name, String gender, int age) {
     this.name = name;
     this.gender = gender;
     this.age = age;
     }
     public String getName() {
     return name;
     }
     public String getGender() {
     return gender;
     }
     public int getAge() {
     return age;
     }
     public static Comparator ageComparator = new Comparator() {
     @Override
     public int compare(JobCandidate jc1, JobCandidate jc2) {
     return (jc2.getAge() < jc1.getAge() ? -1 :
     (jc2.getAge() == jc1.getAge() ? 0 : 1));
     }
     };
     public static Comparator nameComparator = new Comparator() {
     @Override
     public int compare(JobCandidate jc1, JobCandidate jc2) {
     return (int) (jc1.getName().compareTo(jc2.getName()));
     }
     };
     @Override
     public String toString() {
     return " Name: " + this.name + ", Gender: " + this.gender + ", age:" + this.age;
     }
     }

    在上面的类中,从 29 行到 35 行,我们写了一个匿名类并实现了 compare()方法,按照年龄的降序对 JobCandidate 对象进行排序。从37行到42行,我们又写了一个匿名类并实现了 compare() 方法,按照姓名的升序对 JobCandidate进行排序。现在我们写一个类,为委托方对 ArrayList 的元素进行排序。

    JobCandidateSorter.java

    package guru.springframework.blog.sortarraylist.comparator;
     import java.util.ArrayList;
     import java.util.Collections;
     public class JobCandidateSorter {
     ArrayList jobCandidate = new ArrayList<>();
     public JobCandidateSorter(ArrayList jobCandidate) {
     this.jobCandidate = jobCandidate;
     }
     public ArrayList getSortedJobCandidateByAge() {
     Collections.sort(jobCandidate, JobCandidate.ageComparator);
     return jobCandidate;
     }
     public ArrayList getSortedJobCandidateByName() {
     Collections.sort(jobCandidate, JobCandidate.nameComparator);
     return jobCandidate;
     }
     }

    在上面的类中,我们写了 getSortedJobCandidateByAge()方法,在这个方法内部我们调用了 Collections.sort()的重载版本,这个版本传递要被排序的 ArrayList 对象和比较年龄的 Comparator 对象。在 getSortedJobCandidateByName()方法内部,我们又调用了 Collections.sort()的另一个重载版本,这个版本传递要被排序的 ArrayList 对象和比较姓名的 Comparator 对象。

    让我们写一个测试类来测试我们的代码。

    JobCandidateSorterTest.java

    package guru.springframework.blog.sortarraylist.comparator;
     import guru.springframework.blog.sortarraylist.comparator.JobCandidate;
     import guru.springframework.blog.sortarraylist.comparator.JobCandidateSorter;
     import org.junit.Before;
     import org.junit.Test;
     import java.util.ArrayList;
     import static org.junit.Assert.*;
     public class JobCandidateSorterTest {
     JobCandidateSorter jobCandidateSorter;
     @Before
     public void setUp() throws Exception {
     JobCandidate jobCandidate1 = new JobCandidate("Mark Smith", "Male", 26);
     JobCandidate jobCandidate2 = new JobCandidate("Sandy Hunt", "Female", 23);
     JobCandidate jobCandidate3 = new JobCandidate("Betty Clark", "Female", 20);
     JobCandidate jobCandidate4 = new JobCandidate("Andrew Styne", "Male", 24);
     ArrayList jobCandidateList = new ArrayList&lt;&gt;();
     jobCandidateList.add(jobCandidate1);
     jobCandidateList.add(jobCandidate2);
     jobCandidateList.add(jobCandidate3);
     jobCandidateList.add(jobCandidate4);
     jobCandidateSorter = new JobCandidateSorter(jobCandidateList);
     }
     <a href="http://www.jobbole.com/members/madao">@Test</a>
     public void testGetSortedJobCandidateByAge() throws Exception {
     System.out.println("-----Sorted JobCandidate by age: Descending-----");
    ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByAge();
     for (JobCandidate jobCandidate : sortedJobCandidate) {
     System.out.println(jobCandidate);
     }
     }
     <a href="http://www.jobbole.com/members/madao">@Test</a>
     public void testGetSortedJobCandidateByName() throws Exception {
     System.out.println("-----Sorted JobCandidate by name: Ascending-----");
    ArrayList sortedJobCandidate = jobCandidateSorter.getSortedJobCandidateByName();
     for (JobCandidate jobCandidate : sortedJobCandidate) {
     System.out.println(jobCandidate);
     }
     }
     }

    在测试类中我们向 ArrayList 中添加若干 JobCandidate 对象,并使用 Before 注释在测试单元的 setup()方法中创建了一个 JobCandidateSorter 对象。如果你是一个 Junit 新手,可以参考我以前的文章包括 Junit 注释(Junit 单元测试系列)。在 testGetSortedJobCandidateByAge()测试方法中我们调用了 getSortedJobCandidateByAge()方法,并打印了该方法返回的排序后的 ArrayList。在 testGetSortedJobCandidateByName()测试方法中我们调用了getSortedJobCandidateByName()方法并同样打印该方法返回的 ArrayList。测试的输出如下:

    -------------------------------------------------------
    T E S T S
    -------------------------------------------------------
    Running guru.springframework.blog.sortarraylist.comparator.JobCandidateSorterTest
    -----Sorted JobCandidate by name: Ascending-----
    Name: Andrew Styne, Gender: Male, age:24
     Name: Betty Clark, Gender: Female, age:20
     Name: Mark Smith, Gender: Male, age:26
     Name: Sandy Hunt, Gender: Female, age:23
    -----Sorted JobCandidate by age: Descending-----
    Name: Mark Smith, Gender: Male, age:26
     Name: Andrew Styne, Gender: Male, age:24
     Name: Sandy Hunt, Gender: Female, age:23
     Name: Betty Clark, Gender: Female, age:20
     Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.023 sec
    - in guru.springframework.blog.sortarraylist.comparator.JobCandidateSorterTest

    总结

    在本文中我们看到了 ArrayList 排序的不同方法。一种是使用 Comparable 另一种是使用 Comparator。方法的选择一直是造成程序员们困惑的原因之一。你最应该记住的就是一个 Comparable 对象可以说“我可以自己与另外一个对象比较”而一个 Comparator 对象可以说“我可以比较两个不同的对象”。你不能说一个接口比另一个要好。选择的接口取决于你需要实现的功能。

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    抖音安全与信任开放日:揭秘推荐算法,告别单一标签依赖

    ultraedit编辑器打开文件时,总是提示是否转换为DOS格式,如何关闭?

    Cornell大神Kleinberg的经典教材《算法设计》是最好入门的算法教材

    从 Microsoft 下载中心安装 Windows 7 SP1 和 Windows Server 2008 R2 SP1 之前要执行的步骤

    Llama 2基于UCloud UK8S的创新应用

    火山引擎DataTester:如何使用A/B测试优化全域营销效果

    腾讯云、移动云继阿里云降价后宣布大幅度降价

    字节跳动数据平台论文被ICDE2023国际顶会收录,将通过火山引擎开放相关成果

    这个话题被围观超10000次,火山引擎VeDI如此解答

    误删库怎么办?火山引擎DataLeap“3招”守护数据安全

    IT头条

    平替CUDA!摩尔线程发布MUSA 4性能分析工具

    00:43

    三起案件揭开侵犯个人信息犯罪的黑灰产业链

    13:59

    百度三年开放2.1万实习岗,全力培育AI领域未来领袖

    00:36

    工信部:一季度,电信业务总量同比增长7.7%,业务收入累计完成4469亿元

    23:42

    Gartner:2024年全球半导体营收6559亿美元,AI助力英伟达首登榜首

    18:04

    技术热点

    iOS 8 中如何集成 Touch ID 功能

    windows7系统中鼠标滑轮键(中键)的快捷应用

    MySQL数据库的23个特别注意的安全事项

    Kruskal 最小生成树算法

    Ubuntu 14.10上安装新的字体图文教程

    Ubuntu14更新后无法进入系统卡在光标界面解怎么办?

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。