Java 从入门到进阶之路(二十五)
在之前的文章我们介绍了一下 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 从入门到进阶之路(二十五)的更多相关文章
- Java 从入门到进阶之路(十五)
在之前的文章我们介绍了一下 Java 中的接口,本章我们来看一下 Java 中类的多态. 在日常生活中,很多意思并不是我们想要的意思,如下: 1.领导:“你这是什么意思?” 小明:“没什么意思,意思意 ...
- Java 从入门到进阶之路(十二)
在之前的文章我们介绍了一下 Java 类的重写及与重载的区别,本章我们来看一下 Java 类的 private,static,final. 我们在之前引入 Java 类概念的时候是通过商场收银台来引入 ...
- Java 从入门到进阶之路(十八)
在之前的文章我们介绍了一下 Java 中的正则表达式,本章我们来看一下 Java 中的 Object. 在日常生活中,任何事物我们都可以看做是一个对象,在编程中是同样的道理,在 Java 编程中其实更 ...
- Java 从入门到进阶之路(十)
之前的文章我们介绍了一下 Java 中的引用型数组类型,接下来我们再来看一下 Java 中的继承. 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继 ...
- Java 从入门到进阶之路(十四)
在之前的文章我们介绍了一下 Java 中的抽象类和抽象方法,本章我们来看一下 Java 中的接口. 在日常生活中,我们会接触到很多类似接口的问题,比如 USB 接口,我们在电脑上插鼠标,键盘,U盘的时 ...
- Java 从入门到进阶之路(十六)
在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类. 在 Java 中,内部类分为成员内部类和匿名内部类. 我们先来看一下成员内部类: 1.类中套类,外面的叫外 ...
- Java 从入门到进阶之路(十九)
在之前的文章我们介绍了一下 Java 中的Object,本章我们来看一下 Java 中的包装类. 在 Java 中有八个基本类型:byte,short,int,long,float,double,ch ...
- Python 爬虫从入门到进阶之路(十五)
之前的文章我们介绍了一下 Python 的 json 模块,本章我们就介绍一下之前根据 Xpath 模块做的爬取<糗事百科>的糗事进行丰富和完善. 在 Xpath 模块的爬取糗百的案例中我 ...
- Java 从入门到进阶之路(二十)
在之前的文章我们介绍了一下 Java 中的包装类,本章我们来看一下 Java 中的日期操作. 在我们日常编程中,日期使我们非常常用的一个操作,比如读写日期,输出日志等,那接下来我们就看一下 Java ...
- Java 从入门到进阶之路(二十三)
在之前的文章我们介绍了一下 Java 中的 集合框架中的Collection 的迭代器 Iterator,本章我们来看一下 Java 集合框架中的Collection 的泛型. 在讲泛型之前我们先来 ...
随机推荐
- Blender如何设置中文界面
废话不多说,上图 bingo!!
- Myeclipse新建工作空间配置
之前跟着尚硅谷JavaWeb视频学习,现在总结一下Myeclipse新建工作空间配置 Windows按钮下的Preferences 1. General --> Workspace --&g ...
- Redis 入门到分布式 (五) Redis持久化的取舍和选择
个人博客网:https://wushaopei.github.io/ (你想要这里多有) Redis持久化的取舍和选择 持久化的作用 RDB AOF RDB和AOF的选择 一.持久化的作用 ...
- java实现手机尾号评分
30年的改革开放,给中国带来了翻天覆地的变化.2011全年中国手机产量约为11.72亿部.手机已经成为百姓的基本日用品! 给手机选个好听又好记的号码可能是许多人的心愿.但号源有限,只能辅以有偿选号的方 ...
- Java实现第九届蓝桥杯付账问题
付账问题 题目描述 [题目描述] 几个人一起出去吃饭是常有的事.但在结帐的时候,常常会出现一些争执. 现在有 n 个人出去吃饭,他们总共消费了 S 元.其中第 i 个人带了 ai 元.幸运的是,所有人 ...
- DDD之4聚合和聚合根
聚合就是归类的意思,把同类事物统一处理: 聚合根也就是最抽象,最普遍的特性: 背景 领域建模的过程回顾: 那么问题来了? 为什么要在限界上下文和实体之间增加聚合和聚合根的概念,即作用是什么? 如何设计 ...
- C# 反射详解一
首先反射是基于System.Reflection命名空间下,.Net框架提供的帮助类库,可以读取并使用metadata(元数据:描述对象信息的数据). 我们再来看下代码生成编译的总过程. 编译器编译( ...
- 实验二 Linux系统简单文件操作命令
项目 内容 这个作业属于哪个课程 班级课程的主页链接 这个作业的要求在哪里 作业要求链接接地址 学号-姓名 17041428-朱槐健 作业学习目标 1.学习在Linux系统终端下进行命令行操作 2.掌 ...
- springboot使用自定义异常
sprinboot使用自定义注解 创建自定义异常类,继承RuntimeException public class MyException extends RuntimeException { p ...
- Nested Report_FR
设置好下面的关系(Mar 18做,copy from MyQ): 1) Customer.Orders.Items 的 MasterSouce.MasterField2) 后面2个的 DataSour ...