Scala 常用Sort排序
Scala 使用过程中经常要要用到排序模块,自带的方法有sorted,sortBy,sortWith,同时也提供了接口和类,例如Ordering,Ordered,Comparable,Comparator等,下面就盘一下他们的基本用法:
一.sorted
1.sorted-Default
sorted 是基于Ordering 排序
/** Sorts this $coll according to an Ordering.** The sort is stable. That is, elements that are equal (as determined by* `lt`) appear in the same order in the sorted sequence as in the original.** @see [[scala.math.Ordering]]** @param ord the ordering to be used to compare elements.* @return a $coll consisting of the elements of this $coll* sorted according to the ordering `ord`.*/def sorted[B >: A](implicit ord: Ordering[B]): Repr = {val len = this.lengthval b = newBuilderif (len == 1) b ++= thiselse if (len > 1) {b.sizeHint(len)val arr = new Array[AnyRef](len) // Previously used ArraySeq for more compact but slower codevar i = 0for (x <- this) {arr(i) = x.asInstanceOf[AnyRef]i += 1}java.util.Arrays.sort(arr, ord.asInstanceOf[Ordering[Object]])i = 0while (i < arr.length) {b += arr(i).asInstanceOf[A]i += 1}}b.result()}
通过源码我们可以看到sorted有一个隐式参数,这个隐式参数后续可以自己定义排序方法从而让sorted在无形中改变排序规则,另一点,sorted是基于scala编写,但底层调用的是java.util.Arrays.sort。sorted是默认的排序,在scala里适合对单集合进行排序,例如Array[T],ArrayBuffer[T]。sorted默认从小到大排序,如果想要逆序就再调用.reverse即可
test:
val arr = Array(0,2,1)arr.sorted.reverse.foreach(println)
最常见的数组排序,然后逆序返回:
2
1
0
2.sorted-Ordering
trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable
Ordering是继承Compartor实现的接口,其中实现了基本的比大小,最大最小还有反转等基本功能,这里内部的reverse函数比较好玩,reverse实现就是把compare(x:T, y:T)的参数互换位置,实现反比,有兴趣可以看看~ 另一个Ordered和Ordering实现的功能类似,但是使用起来Ordering灵活
test:
// 用户类
class Person(name:String,age:Int) {val name = nameval age = age
}object CompareWithTrait {def main(args: Array[String]): Unit = {val p1 = new Person("a", 24)val p2 = new Person("a", 22)val p3 = new Person("b", 15)val list = List(p1, p2, p3)// sorted接口需要implicit object PersonOrdering extends Ordering[Person] {override def compare(p1: Person, p2: Person): Int = {p1.name == p2.name match {case false => -p1.name.compareTo(p2.name)case _ => p1.age - p2.age}}}list.sorted.foreach(x => println(x.name,x.age))
}
通过定义源码中的隐函数参数,实现了自定义sorted。这里首先定义一个Demo的用户类,只有两个简单属性name和age,下面测试函数我们只需要初始化几个用户,然后自己重写override compare方法,注意这里采用implicit隐式定义,正常情况下如果我们使用别人提供的包,一些隐式方法我们是感知不到的,例如我会默认把我类里的Int变成String,这样我有其他函数需要传String参数时,传Int也不会报错;
implicit def intToString(number: Int): String ={number.toString}
这里隐式函数就是给Sorted使用,正常情况我们也无法感知,compare通过返回的Int判断两边的大小,大于0是前者大于后者,小于0同理,等于0就默认顺序了。这里compare首先按照姓名逆序排列,然后再按照年龄顺序排列,所以看下结果:
(b,15)
(a,22)
(a,24)
Ordered的写法这里就不写了,用了一下确实没有Ordering好使~
3.sorted-Comparable
刚才的Ordering继承了Comparable,二者一个是scala的接口,一个是java的接口,这里略去很多的注释,这个接口我们只需要实现compareTo,与Ordering类似,需要通过Int的正负返回比较的两个对象的大小,o就是要比的,this就是自己
public interface Comparable<T> {/**...* @param o the object to be compared.* @return a negative integer, zero, or a positive integer as this object* is less than, equal to, or greater than the specified object.** @throws NullPointerException if the specified object is null* @throws ClassCastException if the specified object's type prevents it* from being compared to this object.*/public int compareTo(T o);
}
test:
object CompareWithComparable {def main(args: Array[String]): Unit = {val p1 = new CompareWithComparable(5)val p2 = new CompareWithComparable(10)val p3 = new CompareWithComparable(8)val stArr = Array(p1,p2,p3)stArr.sorted.foreach(x => println(x.age))}
}class CompareWithComparable(val age: Int) extends java.lang.Comparable[CompareWithComparable] {override def compareTo(p: CompareWithComparable): Int = {this.age - p.age}
}
和上面的person类似,这里只是简单的比较了年龄大小,当然里面也可以写很复杂的逻辑,不过这里我们应该遵循如下规则,否则代码将会出现一些奇怪的异常:
对于所有的x,y,z
tips:sgn是常用的符号函数,返回+1,-1,0
对称性: sgn(x.compareTo(y)) == -sgn(y.compareTo(x))
传递性: x.compareTo(y) > 0 && y.compareTo(z) > 0 则 x.compareTo(z) > 0
等价替换: x.compareTo(y) == 0 则 sgn(x.compareTo(z)) == sgn(y.compareTo(z))
相等性(待定): x.compareTo(y) == 0 等价于 x.equals(y)
前3个特性和重写equals的要求比较类似,第四个则并不是需要严格执行,参考sorted-Ording例子中,我们有可能存在两个人同名,同龄,但是其他属性不同,所以这里compare并不像equals那样严格要求相等。还有一个类似的comparator接口
public interface Comparator<T> {int compare(T o1, T o2);boolean equals(Object obj);
}
两个compare的区别是前者需要override compare()方法,后者则override compareTo方法,上面说到的Ordering其实就是继承了Comparator,所以我们复写了compare方法。
如果不定义隐函数或者继承Comparable直接对一个类进行sorted会报错:
Error:(35, 22) No implicit Ordering defined for xxx
二.SortedBy
sortedBy需要指定你要通过哪个元素排序,可以针对普通数组,也可以针对有参数的类
1.普通数组
val arr = Array((1,2),(2,1),(3,3))arr.sortBy(_._2).foreach(println)
指定通过元祖的第二位排序
(2,1)
(1,2)
(3,3)
2.类
class person(val age: Int) {def getAge(): Int = age
} val arr = Array(new person(1),new person(10),new person(5))
arr.sortBy(-_.getAge()).foreach(p => println(p.getAge()))
简单类的排序,通过-号可以实现逆序
10
5
1
三.Sort with
def sortWith(lt: (A, A) => Boolean): Repr = sorted(Ordering fromLessThan lt)
前面的排序通过返回的Int做排序的判断依据,sortWith采用Boolean,换汤不换药,把减法变成了判断两个变量大小,这里看源码发现其实sortWith也是sorted的一种特殊形态
test:
def fn(p1: person, p2: person) = (p1.age > p2.age)A:arr.sortWith(fn).foreach(p => println(p.age))B:arr.sortWith((p1,p2) => p1.age > p2.age).foreach(p => println(p.age))
通过定义返回boolean的函数,判断两个类,A,B两种写法均可,A适合写复杂逻辑
10
5
1
Scala 常用Sort排序相关推荐
- 常用的排序算法的时间复杂度和空间复杂度
常用的排序算法的时间复杂度和空间复杂度 1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出 ...
- 5种JavaScript中常用的排序方法
5种JavaScript中常用的排序方法 01.冒泡排序 通过相邻数据元素的交换,逐步将待排序序列变为有序序列,如果前面的数据大于后面的数据,就将两值进行交换,将数据进行从小到大的排序,这样对数组的第 ...
- STL常用的排序算法
常用的排序算法 merge() sort() random_shuffle() reverse() merge() 以下是排序和通用算法:提供元素排序策略 merge: 合并两个有序序列,存放到另一个 ...
- php1到5000排序,常用的排序算法(一)--快速排序(PHP实现)
常用的排序算法系列 快速排序 假设当前需要从小到大进行排序,快速排序的核心思路是,从当前数组中,找到一个元素作为基准比较值(key),分别从两个方向进行比较.从后往前找,比key小元素放在数组前面.然 ...
- Golang sort 排序
1.前言 开发过程中,我们经常需要对元素进行排序,使用 Go 我们可以轻松实现. Go 内置 sort 包中提供了根据一些排序函数可对任何序列进行排序,并提供自定义排序规则的能力. sort 包实现了 ...
- C基础 工程中常用的排序
引言 - 从最简单的插入排序开始 很久很久以前, 也许都曾学过那些常用的排序算法. 那时候觉得计算机算法还是有点像数学. 可是脑海里常思考同类问题, 那有什么用呢(屌丝实践派对装逼学院派的深情鄙视). ...
- Scala之sorted排序的使用
一.sort排序 1.1 sorted (1)简单数据结构 val list1 = List(30, 50, 70, 60, 10, 20) println(list1.sorted) (2)复杂的数 ...
- 【JavaScript】 sort排序
排序方法 插入排序:几个数排好序,再来一个数和排好序的最后一个数比,再与前一个比,-,插入. 二分插入排序:几个数排好序,再来一个数和中间数比,再与左/右的中间数比,-,插入. 归并排序:每两个排序, ...
- sort排序方法的实现原理
sort 排序方法的实现原理 我们比较常用的是直接调用 JS的 sort方法,围绕原生 JS方法,并结合 V8排序的代码一起来分析,以便碰到类似的 JS排序问题时能够轻松应对. 在开始前请思考 ...
最新文章
- AI发展这一年:不断衍生的技术丑闻与抵制声潮
- SAP创建生产订单时要求输入销售订单
- 关于海量数据的SQL查询优化.........
- POJ 2533 Longest Ordered Subsequence 动态规划
- 服务器系统崩溃文件系统损坏,explorer启动崩溃,提示文件系统错误-2147219200
- shouldoverrideurlloading为什么有时候不走_为什么付出越多,对方就越不懂得感恩,婚姻有时候也需要斤斤计较...
- opensips mysql 版本_Opensips-1.11版本安装过程
- vscode统计代码行数
- CruiseControl入门简介
- Html网页设计-动漫网站设计
- windows 7 多国语言包官方下载资源共享(32/64位)
- 爬虫--网络数据采集
- php yar 安装失败_全面解析php7安装yar扩展的方法
- android重力传感器横竖反,Android重力传感器--随重力旋转的图标
- HowToDoIt 开源框架爱好者组织发布第一份项目总结
- RMAN 下CROSSCHECK命令 详解
- vue + element-ui 对登录功能、重置表单、退出功能、路由重定向、挂载路由导航守卫的实现
- python3 删除指定文件夹重复文件
- 大学物理——质点运动学
- mysql 时间盲注语句,sql注入学习记录(5)-基于时间延迟的SQL盲注