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 的泛型. 在讲泛型之前我们先来 ...
随机推荐
- Java实现 LeetCode 747 至少是其他数字两倍的最大数(暴力)
747. 至少是其他数字两倍的最大数 在一个给定的数组nums中,总是存在一个最大元素 . 查找数组中的最大元素是否至少是数组中每个其他数字的两倍. 如果是,则返回最大元素的索引,否则返回-1. 示例 ...
- Java实现 LeetCode 392 判断子序列
392. 判断子序列 给定字符串 s 和 t ,判断 s 是否为 t 的子序列. 你可以认为 s 和 t 中仅包含英文小写字母.字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符 ...
- Java实现 LeetCode 222 完全二叉树的节点个数
222. 完全二叉树的节点个数 给出一个完全二叉树,求出该树的节点个数. 说明: 完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集 ...
- Android studio环境配置(运行报错)
报错的种类有很多,下面的方法能解决大多数: 所有路径不能用中文,不能有空格,逗号句号也不能用中文,项目文件路径也不行 首先要配置Java环境,这个就不多说了, 这里有以下JAVA_HOME的配置,下图 ...
- java实现最大五个数
** 最大5个数** [12,127,85,66,27,34,15,344,156,344,29,47,....] 这是某设备测量到的工程数据. 因工程要求,需要找出最大的5个值. 一般的想法是对它排 ...
- java实现第六届蓝桥杯加法变乘法
加法变乘法 题目描述 我们都知道:1+2+3+ - + 49 = 1225 现在要求你把其中两个不相邻的加号变成乘号,使得结果为2015 比如: 1+2+3+-+1011+12+-+2728+29+- ...
- java实现第四届蓝桥杯剪格子
剪格子 题目描述 如图p1.jpg所示,3 x 3 的格子中填写了一些整数. 我们沿着图中的红色线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子 ...
- python自学Day03(自学书籍python编程从入门到实践)
第4章 操作列表 只需要几行代码无论列表有多长,循环都能够让我对列表的每个元素都采取一个或一系列相同的措施,从而高效的处理任何长度的列表. 4.1 遍历整个列表 对列表中每个元素都拿出来,进行一个或者 ...
- k8s学习-安全
4.8.安全 4.8.1.概念 一些内容可参考4.6.2.Secret的内容 说明 Kubernetes 作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务.API Server 是集群 ...
- SpringBoot爬坑系列
1.日志篇 现象 由于日志配置采用原来SpringMVC项目中的log4j.properties 文件,日志采用springboot自带的jar包会出现打印不出日志的情况. 解决 引入原日志包 < ...