一、背景
在实际的需求中,我们需要根据对象的各种属性(标题,时间,点击率,销售额…)进行排序(升序,降序),可以在数据库的sql上进行处理,但是 不是每一个场景 都适合在sql上进行处理,我们有时候需要在程序根据不同的属性,对一个对象进行各种排序 通过页面呈现给用户。
二、java实现
1、实现Comparable,Comparator接口
/**
* 商品po类
*/
public class Items implements java.lang.Comparable<Items> {
private String title;
private int hits;
private Date pubTime;
public Items() {}
public Items(String title, int hits, Date pubTime) {
super();
this.title = title;
this.hits = hits;
this.pubTime = pubTime;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getHits() {
return hits;
}
public void setHits(int hits) {
this.hits = hits;
}
public Date getPubTime() {
return pubTime;
}
public void setPubTime(Date pubTime) {
this.pubTime = pubTime;
}
//时间降序 点击量升序 标题降序
@Override
public int compareTo(Items o) {
int result = 0;
//按照生产时间降序
result = - this.pubTime.compareTo(o.pubTime);
if(0==result){//如果生产时间相同 就按照销售量升序排列
result = this.hits-o.hits;
if(0==result){//如果销售量相同 按照名字降序排列
result = - this.title.compareTo(o.title);
}
}
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("商品名称").append(this.title);
sb.append("销售量").append(this.hits);
sb.append("生产时间").append(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.pubTime)).append("\n");
return sb.toString();
}
}
测试代码:
//时间降序, 销售量升序, 标题降序
public static void main(String[] args) {
List<Items> item = new ArrayList<Items>();
item.add(new Items("abcitems",30,new Date(System.currentTimeMillis()-1000*60*60)));
item.add(new Items("abcfgitems",30,new Date(System.currentTimeMillis()-1000*60*50)));
item.add(new Items("abcditems",100,new Date()));
item.add(new Items("abefNews",50,new Date(System.currentTimeMillis()-1000*60*60)));
System.out.println("----------排序前----------");
System.out.println(item);
System.out.println("----------排序后----------");
Collections.sort(item);
System.out.println(item);
}
2、重写compare方法 实现排序
首先,定义比较的业务规则
/**
* 定义业务的比较规则,我需要按照字符串的长度进行比较(在实际的场景中,可以根据业务的需求,灵活的改变比较规则,实现排序)
*/
public class CompareString implements java.util.Comparator<String> {
@Override
public int compare(String o1, String o2) {
int len1 = o1.length();
int len2 = o2.length();
return -(len1-len2);//需要按照降序排列
}
}
测试代码:
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("abc");
list.add("abcd");
list.add("ab");
list.add("abd");
Collections.sort(list,new CompareString());
System.out.println(list);
//[abcd, abc, abd, ab]
}
三、kotlin实现
1、实现Comparable,Comparator接口
如需为用户定义的类型定义一个自然顺序,可以让这个类型继承 Comparable。 这需要实现 compareTo() 函数。 compareTo() 必须将另一个具有相同类型的对象作为参数并返回一个整数值来显示哪个对象更大:
- 正值表明接收者对象更大。
- 负值表明它小于参数。
- 0 说明对象相等。
class Version(val major: Int, val minor: Int): Comparable<Version> {
override fun compareTo(other: Version): Int {
if (this.major != other.major) {
return this.major - other.major
} else if (this.minor != other.minor) {
return this.minor - other.minor
} else return 0
}
}
fun main() {
println(Version(1, 2) > Version(1, 3))
println(Version(2, 0) > Version(1, 5))
}
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
2、重写compare方法 实现排序
自定义 顺序让你可以按自己喜欢的方式对任何类型的实例进行排序。 特别是,你可以为不可比较类型定义顺序,或者为可比较类型定义非自然顺序。 如需为类型定义自定义顺序,可以为其创建一个 Comparator。 Comparator 包含 compare() 函数:它接受一个类的两个实例并返回它们之间比较的整数结果。 如上所述,对结果的解释与 compareTo() 的结果相同。
val lengthComparator = Comparator { str1: String, str2: String -> str1.length - str2.length }
println(listOf("aaa", "bb", "c").sortedWith(lengthComparator))
有了 lengthComparator,你可以按照字符串的长度而不是默认的字典顺序来排列字符串。
定义一个 Comparator 的一种比较简短的方式是标准库中的 compareBy() 函数。 compareBy() 接受一个 lambda 表达式,该表达式从一个实例产生一个 Comparable 值,并将自定义顺序定义为生成值的自然顺序。 使用 compareBy(),上面示例中的长度比较器如下所示:
println(listOf("aaa", "bb", "c").sortedWith(compareBy { it.length }))
为了按照自定义顺序排序或者对不可比较对象排序,可以使用函数 sortedBy() 和 sortedByDescending()。 它们接受一个将集合元素映射为 Comparable 值的选择器函数,并以该值的自然顺序对集合排序。
val numbers = listOf("one", "two", "three", "four")
val sortedNumbers = numbers.sortedBy { it.length }
println("Sorted by length ascending: $sortedNumbers")
val sortedByLast = numbers.sortedByDescending { it.last() }
println("Sorted by the last letter descending: $sortedByLast")