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.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出 ...

  2. 5种JavaScript中常用的排序方法

    5种JavaScript中常用的排序方法 01.冒泡排序 通过相邻数据元素的交换,逐步将待排序序列变为有序序列,如果前面的数据大于后面的数据,就将两值进行交换,将数据进行从小到大的排序,这样对数组的第 ...

  3. STL常用的排序算法

    常用的排序算法 merge() sort() random_shuffle() reverse() merge() 以下是排序和通用算法:提供元素排序策略 merge: 合并两个有序序列,存放到另一个 ...

  4. php1到5000排序,常用的排序算法(一)--快速排序(PHP实现)

    常用的排序算法系列 快速排序 假设当前需要从小到大进行排序,快速排序的核心思路是,从当前数组中,找到一个元素作为基准比较值(key),分别从两个方向进行比较.从后往前找,比key小元素放在数组前面.然 ...

  5. Golang sort 排序

    1.前言 开发过程中,我们经常需要对元素进行排序,使用 Go 我们可以轻松实现. Go 内置 sort 包中提供了根据一些排序函数可对任何序列进行排序,并提供自定义排序规则的能力. sort 包实现了 ...

  6. C基础 工程中常用的排序

    引言 - 从最简单的插入排序开始 很久很久以前, 也许都曾学过那些常用的排序算法. 那时候觉得计算机算法还是有点像数学. 可是脑海里常思考同类问题, 那有什么用呢(屌丝实践派对装逼学院派的深情鄙视). ...

  7. Scala之sorted排序的使用

    一.sort排序 1.1 sorted (1)简单数据结构 val list1 = List(30, 50, 70, 60, 10, 20) println(list1.sorted) (2)复杂的数 ...

  8. 【JavaScript】 sort排序

    排序方法 插入排序:几个数排好序,再来一个数和排好序的最后一个数比,再与前一个比,-,插入. 二分插入排序:几个数排好序,再来一个数和中间数比,再与左/右的中间数比,-,插入. 归并排序:每两个排序, ...

  9. sort排序方法的实现原理

    sort 排序方法的实现原理   我们比较常用的是直接调用 JS的 sort方法,围绕原生 JS方法,并结合 V8排序的代码一起来分析,以便碰到类似的 JS排序问题时能够轻松应对.   在开始前请思考 ...

最新文章

  1. AI发展这一年:不断衍生的技术丑闻与抵制声潮
  2. SAP创建生产订单时要求输入销售订单
  3. 关于海量数据的SQL查询优化.........
  4. POJ 2533 Longest Ordered Subsequence 动态规划
  5. 服务器系统崩溃文件系统损坏,explorer启动崩溃,提示文件系统错误-2147219200
  6. shouldoverrideurlloading为什么有时候不走_为什么付出越多,对方就越不懂得感恩,婚姻有时候也需要斤斤计较...
  7. opensips mysql 版本_Opensips-1.11版本安装过程
  8. vscode统计代码行数
  9. CruiseControl入门简介
  10. Html网页设计-动漫网站设计
  11. windows 7 多国语言包官方下载资源共享(32/64位)
  12. 爬虫--网络数据采集
  13. php yar 安装失败_全面解析php7安装yar扩展的方法
  14. android重力传感器横竖反,Android重力传感器--随重力旋转的图标
  15. HowToDoIt 开源框架爱好者组织发布第一份项目总结
  16. RMAN 下CROSSCHECK命令 详解
  17. vue + element-ui 对登录功能、重置表单、退出功能、路由重定向、挂载路由导航守卫的实现
  18. python3 删除指定文件夹重复文件
  19. 大学物理——质点运动学
  20. mysql 时间盲注语句,sql注入学习记录(5)-基于时间延迟的SQL盲注

热门文章

  1. 机器学习之朴素贝叶斯二、情感分析实践
  2. zypper包管理器
  3. CAN FD 链路协议详细说明
  4. 英语口语exam4(environmental protect)
  5. 连微信也封不住的私域流量大爆发,商家该如何把握好时代风口,系统理解把握私域流量风口!...
  6. 【KMP算法】详细讲解
  7. 南昌大学计算机调剂难吗,说说我调剂的感受
  8. Python 爬虫 - 获取百度关键字搜索内容
  9. MATLAB 函数或变量 ‘XXX’ 无法识别
  10. python种颜色循环_python图像主色调(主颜色)提取,在hsv空间k均值迭代实现