在之前的文章我们介绍了一下 Java 中的  集合框架中的Collection 的子接口 List的 增删改查和与数组间相互转换的方法,本章我们来看一下 Java 集合框架中的Collection 的子接口 List 的另外一些方法。

我们在使用集合的时候难免会对其中的元素进行排序,因为 Set 集合本身是无序的,所以本章将着重讲解 List 集合,如下:

 import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random; /**
* 排序集合元素
* 排序集合使用的是集合的工具类 Collections 的静态方法 sort
* 排序仅能对 List 集合进行,因为 Set 部分实现类是无序的
* */
public class Main {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
Random random = new Random();
for(int i=0;i<10;i++){
list.add(random.nextInt(100));
}
System.out.println(list); // [49, 24, 29, 59, 56, 1, 1, 5, 49, 60] Collections.sort(list);
System.out.println(list); // [1, 1, 5, 24, 29, 49, 49, 56, 59, 60]
}
}

在上面的代码中,我们随机生成了一些正数并添加到 List 集合中,我们通过 sort 方法,系统变自动按照自然数的排列方法为我们做好了排序,很是方便,那如果 List 中使我们自己定义的内容,比如说一个类,那该如何排序呢,如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List; /**
* 排序集合元素
* 排序集合使用的是集合的工具类 Collections 的静态方法 sort
* 排序仅能对 List 集合进行,因为 Set 部分实现类是无序的
*/
public class Main {
public static void main(String[] args) {
List<Point> list = new ArrayList<Point>();
list.add(new Point(1, 2));
list.add(new Point(2, 3));
list.add(new Point(4, 2));
list.add(new Point(2, 5));
list.add(new Point(9, 3));
list.add(new Point(7, 1));
System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (9, 3), (7, 1)]
// Collections.sort(list); // 编译错误,不知道 Point 排序规则
/**
* sort 方法要求集合必须实现 Comparable 接口
* 该接口用于规定实现类事可以比较的
* 其中一个 compareTo 方法时用来定义比较大小的规则
* */
Collections.sort(list);
System.out.println(list); // [(1, 2), (2, 3), (4, 2), (2, 5), (7, 1), (9, 3)] }
} class Point implements Comparable<Point> { // 定义为泛型 T 类型
private int x;
private int y; public Point(int x, int y) {
this.x = x;
this.y = y;
} public int getX() {
return x;
} public void setX(int x) {
this.x = x;
} public int getY() {
return y;
} public void setY(int y) {
this.y = y;
} @Override
public String toString() {
return "(" + x + ", " + y + ")";
} /**
* 当实现了 Comparable 接口后,需要重写下面的方法
* 该方法的作用是定义当前对象与给定参数对象比较大小的规则
* 返回值为一个 int 值,该值表示大小关系
* 它不关注具体的取值是多少,而关注的是取值范围
* 当返回值 >0 时:当前对象不参数对象大
* 当返回值 <0 时:当前对象比参数对象小
* 当返回值 =0 时:两个对象相等
*/
@Override
public int compareTo(Point o) {
/**
* 比较规则,点到原点的距离长的打
* */
int len = this.x * this.x + this.y * this.y;
int olen = o.x * o.x + o.y * o.y;
return len - olen;
}
}

在上面的代码中,我们跟之前一样定义了一个 Point 类,然后实例化后存入 list 集合中,如果我们相对 Point 进行排序,如果直接调用 sort 方法会报错,这是由于编译器不知道我们定义的 Point 类的排序规则,所以我们需要通过接口 Comparable 接口来自定义排序规则,如下图:

我们可以通过坐标系中点到原点的距离来判断 Point 的大小,即 x*x+y*y 的大小,然后通过重写 compareTo 方法来实现 sort 。

实际上虽然能实现,但是并不理想,为了实现一个 sort 方法,要求我们的集合元素必须实现 Comparable 接口并且定义比较规则,这种我们想使用某个功能,而它要求我们修改程序的现象称为“侵入性”。修改的代码越多,侵入性越强,越不利于程序的扩展。

我们再来看一下下面的排序:

 import java.util.ArrayList;
import java.util.Collections;
import java.util.List; public class Main {
public static void main(String[] args) {
List<String> list1 = new ArrayList<String>();
list1.add("Java");
list1.add("c++");
list1.add("Python");
list1.add("PHP");
Collections.sort(list1);
System.out.println(list1); // [Java, PHP, Python, c++] List<String> list2 = new ArrayList<String>();
list2.add("孙悟空");
list2.add("猪八戒");
list2.add("唐僧");
list2.add("六小龄童");
Collections.sort(list2);
System.out.println(list2); // [六小龄童, 唐僧, 孙悟空, 猪八戒] }
}

在上面的排序中,当我们对字母或汉字进行排序时,其实是比的第一个字的 Unicode 码,那如果我们不使用 Comparable 的接口该如何自定义我们想要的实现规则呢?比如根据字符串的长度来进行排序,其实 sort 有一个额外的重载方法来实现我们想要的结果,如下:

 import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; public class Main {
public static void main(String[] args) {
/**
* 重载的 sort 方法要求传入一个额外的比较器
* 该方法不再要求集合元素必须实现 Comparable 接口
* 并且不再使用集合元素资深的比较规则排序了
* 而是根据给定的这个额外的比较器的比较规则对集合元素进行排序
* 实际开发中也推荐使用这种方式进行集合元素排序
* 若集合元素是自定义的
* 创建比较器时推荐使用匿名内部类的形式
*/
List<String> list1 = new ArrayList<String>();
list1.add("Java");
list1.add("c++");
list1.add("Python");
list1.add("PHP");
MyComparator myComparator1 = new MyComparator();
Collections.sort(list1, myComparator1); // 重载 sort
System.out.println(list1); // [c++, PHP, Java, Python] List<String> list2 = new ArrayList<String>();
list2.add("孙悟空");
list2.add("猪八戒");
list2.add("唐僧");
list2.add("六小龄童");
// 匿名内部类形式创建
Comparator<String> myComparator2 = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
Collections.sort(list2, myComparator2); // 重载 sort
System.out.println(list2); // [唐僧, 孙悟空, 猪八戒, 六小龄童] }
} /**
* 定义一个额外的比较器
* 该方法用来定义 o1 和 o2 的比较
* 若返回值 >0:o1>o2
* 若返回值 <0:o1<o2
* 若返回值 =0:两个对象相等
*/
class MyComparator implements Comparator<String> {
@Override
public int compare(String o1, String o2) {
/**
* 字符串中字符多的大
* */
return o1.length() - o2.length();
}
}

Java 从入门到进阶之路(二十五)的更多相关文章

  1. Java 从入门到进阶之路(十五)

    在之前的文章我们介绍了一下 Java 中的接口,本章我们来看一下 Java 中类的多态. 在日常生活中,很多意思并不是我们想要的意思,如下: 1.领导:“你这是什么意思?” 小明:“没什么意思,意思意 ...

  2. Java 从入门到进阶之路(十二)

    在之前的文章我们介绍了一下 Java 类的重写及与重载的区别,本章我们来看一下 Java 类的 private,static,final. 我们在之前引入 Java 类概念的时候是通过商场收银台来引入 ...

  3. Java 从入门到进阶之路(十八)

    在之前的文章我们介绍了一下 Java 中的正则表达式,本章我们来看一下 Java 中的 Object. 在日常生活中,任何事物我们都可以看做是一个对象,在编程中是同样的道理,在 Java 编程中其实更 ...

  4. Java 从入门到进阶之路(十)

    之前的文章我们介绍了一下 Java 中的引用型数组类型,接下来我们再来看一下 Java 中的继承. 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继 ...

  5. Java 从入门到进阶之路(十四)

    在之前的文章我们介绍了一下 Java 中的抽象类和抽象方法,本章我们来看一下 Java 中的接口. 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时 ...

  6. Java 从入门到进阶之路(十六)

    在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类. 在 Java 中,内部类分为成员内部类和匿名内部类. 我们先来看一下成员内部类: 1.类中套类,外面的叫外 ...

  7. Java 从入门到进阶之路(十九)

    在之前的文章我们介绍了一下 Java 中的Object,本章我们来看一下 Java 中的包装类. 在 Java 中有八个基本类型:byte,short,int,long,float,double,ch ...

  8. Python 爬虫从入门到进阶之路(十五)

    之前的文章我们介绍了一下 Python 的 json 模块,本章我们就介绍一下之前根据 Xpath 模块做的爬取<糗事百科>的糗事进行丰富和完善. 在 Xpath 模块的爬取糗百的案例中我 ...

  9. Java 从入门到进阶之路(二十)

    在之前的文章我们介绍了一下 Java 中的包装类,本章我们来看一下 Java 中的日期操作. 在我们日常编程中,日期使我们非常常用的一个操作,比如读写日期,输出日志等,那接下来我们就看一下 Java ...

  10. Java 从入门到进阶之路(二十三)

    在之前的文章我们介绍了一下 Java 中的  集合框架中的Collection 的迭代器 Iterator,本章我们来看一下 Java 集合框架中的Collection 的泛型. 在讲泛型之前我们先来 ...

随机推荐

  1. 树莓派4B获取IP地址的几种简易方法

    首先声明一下,使用的是Paspbian系统,其实其他系统和本文说的获取IP地址关系也不大. 1.当你有路由器,有PC客户端的情况,你把你的树莓派用网线将其连接起来.你可以借助这个软件,advanced ...

  2. go语言的主要特征

    go语言主要特征 1.自动立即回收. 2.更丰富的内置类型. 3.函数多返回值. 4.错误处理. 5.匿名函数和闭包. 6.类型和接口. 7.并发编程. 8.反射. 9.语言交互性. golang文件 ...

  3. Java实现 蓝桥杯VIP 算法提高 分数统计

    算法提高 分数统计 时间限制:1.0s 内存限制:512.0MB 问题描述 2016.4.5已更新此题,此前的程序需要重新提交. 问题描述 给定一个百分制成绩T,将其划分为如下五个等级之一: 9010 ...

  4. java代码(1)---Java8 Lambda

     Lambda 一.概述   1.什么是Lambda表达式 //1.不需要参数,返回值为5 () -> 5 //2.接收一个参数(数字类型),返回其2倍的值 x -> 2 * x //3. ...

  5. Linux RPM管理命令

    RPM安装 rpm -ivh 包全名,其中,-i 表示安装,-v 表示显示详细信息,-h 表示显示进度 手动安装会有很多包依赖需要解决,如果是模块依赖,可以使用rpmfind进行查询解决 RPM升级 ...

  6. 循序渐进VUE+Element 前端应用开发(8)--- 树列表组件的使用

    在我前面随笔<循序渐进VUE+Element 前端应用开发(6)--- 常规Element 界面组件的使用>里面曾经介绍过一些常规的界面组件的处理,主要介绍到单文本输入框.多文本框.下拉列 ...

  7. 实验五 shell脚本编程

    项目 内容 这个作业属于哪个课程 课程链接 这个作业的要求在哪里 作业要求 学号-姓名 17041428-朱槐健 作业学习目标 1. 了解shell脚本的概念及使用 2.掌握shell脚本语言的基本语 ...

  8. Promise相关学习

    what? Promise对象表示一个异步操作的最终状态(完成或失败),以及其返回的值 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/ ...

  9. Python 报错:NameError: name 'ctypes' is not defined

    使用python中的ctypes模块可以很方便的调用windows的dll(也包括linux下的so等文件) 引入ctypes库 有两种方法 from ctypes import * import c ...

  10. 手写网页扫雷之HTML部分

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...