Day17:比大小

记得初学Java的时候,若要对List进行排序,可以使用Collections的静态方法sort(),若List里面装的是基本型态(Primitive Type)的数值以及字串(String)就可以直接由小到大排序;不过若是想要由大到小排序的时候,就会看到下面这样的写法:

List<Integer> list = Arrays.asList(2, 1, 3);
Collections.sort(list, (i1, i2) -> -i1.compareTo(i2));

我那时就有2个疑惑:这个compareTo()是哪来的?怎麽印象中还有个方法是compare()?而又为什麽只要在原本的compareTo结果上加一个负号,就会是变成相反的排序呢?

要解除这2个疑惑,就需要了解到Comparable介面以及Comparator介面了。

首先为什麽我们可以直接针对装有基本型态或者字串的List来进行Collections的sort方法呢?这是因为这些类别的比较规则Java都帮我们写好了~

如果查看Integer, Float, String等类别,会发现他们都实作(implements)了Comparable介面,而Comparable介面就只有一个compareTo方法,会回传一个int值:
obj1.compareTo(obj2) 大於0:obj1排序大於obj2,会被排到後面
obj1.compareTo(obj2) 等於0:obj1排序与obj2相等
obj1.compareTo(obj2) 小於0:obj1排序小於obj2,会被排到前面

所以Collections.sort(List)的方法实作就是叫用每个元素的compareTo来进行比大小,所以如果我们的List里头放的是我们自己定义的类别物件,那我们就必须要实作Comparable介面并覆写(Override) compareTo 方法。

但有办法每个物件都去实作Comparable吗?又或者当我们想要帮基本型态或字串等类别自己定义其他比较规则时,就没辙了吗?(没辙因为基本型态与String都被冠上了final)

这时Comparator就登场了~Comparator介面中的compare()方法就相当於Comparable的compareTo(),我们比对观察一下:
Comparable:int compareTo(T o)
Comparator:int compare(T o1, T o2)

这两者的差别在於参数的数量以及由什麽物件来呼叫。compareTo是直接被实作在有实施Comparable的类别中,所以是由该物件实例来直接呼叫,引数只要放入另一个要拿来被比较的物件就好了;Comparator则是类似一个额外工具的概念,并不是直接定义在物件的类别之中,所以要使用时需要传入2个要进行比较的物件。回传值的定义是一样的。

这样的做法就让我们可以自由定义compare所需要的排序比较规则了!

而我们在Java API Collections的sort()方法中可以看到有两个重载(overload)版本:
sort(List list)
sort(List list, Comparator<? super T> c)
我们就可以把自己定义的Comparator利用重载版本的sort来使用罗。

小结:

  • Comparable介面是由各类别来implements,并各类别中实作compareTo(T o1)方法。
  • Comparator介面要视欲进行排序的方法支不支援传入Comparator引数,若可以传入的话就可以自行定义compare(T o1, T o2)的排序规则。

<<:  Angular-开发工具&安装AngularCLI(Day15)

>>:  AE新手必学の三种常用追踪方法02-Day29

远程控制的方法

这是我摸Raspberry pi的第15天 每次都要接萤幕以及无线键盘与滑鼠 之前原本就想这样的模式...

【必收藏系列】查找并清理 Mac 上重复的档案/图片

日常我们在使用 Mac 机时,总是很容易重复下载一些档案或图片,例如 复制整理档案或移动档案时,很容...

【Vue】Vue Router 设定路由| 专案实作

为什麽要设定路由呢? 过去的网页大多是 Multi Page Application(多页式应用程序...

换了一个框架

今天学一下flask这个框架 因为django卡关所以不太想卡在那边 也没人可以问我就换框架看看 找...

[30天 Vue学好学满 DAY23] Vue Router-2

昨天笔记了基础Vue Router 以及 History概念,今天继续笔记其他细项用法。 动态路由 ...