最近老有人问我数据排序(很常见的功能,比如参加各种竞赛得分、游戏厅得分排行榜)的问题,我就总结下我是怎么给数据排序的,注意无序数据不一定来源于数据库(但实际上大部分情况来源于数据库检索),个人经历排序实现分三类:
第一类:直接通过sql语句
sql样本
create table ZHJDKP_CODE_TABLES
(
ID NUMBER(20) not null,
TYPEID NUMBER(20) not null,
VALUE VARCHAR2(100),
CODE VARCHAR2(200),
YXBZ VARCHAR2(1)
);
alter table ZHJDKP_CODE_TABLES
add primary key (ID);
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (1, 1, 'text', '01', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (2, 1, 'select', '02', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (3, 1, 'textarea', '03', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (4, 1, 'checkbox', '04', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (5, 1, 'radio', '05', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (6, 1, 'label', '06', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (7, 1, 'open', '07', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (8, 1, 'filter', '08', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (9, 1, 'img', '09', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (10, 2, '曲线图', 'line', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (11, 2, '多曲线图', 'mulline', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (12, 2, '多柱状图', 'mulbar', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (13, 2, '饼状图', 'pie', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (14, 2, '柱状图', 'bar', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (15, 2, '锥状图', 'streamlinefunnel', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (16, 2, '区域图', 'area', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (17, 2, '球状图', 'bubble', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (18, 2, '圆圈图', 'doughnut', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (19, 2, '列状图', 'column', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (20, 3, '稽查类', '01', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (21, 4, '权限税务机关处理', '01', 'N');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (22, 4, '人员处理', '02', 'N');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (23, 4, '确认处理', '03', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (24, 4, '岗位处理', '04', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (25, 4, '人工处理', '05', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (26, 4, '自定义处理', '07', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (27, 4, '税务机关处理', '08', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (28, 5, 'number', '01', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (29, 5, 'date', '02', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (30, 5, 'money', '03', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (31, 5, 'time', '04', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (32, 5, 'percent', '05', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (33, 6, 'window', '01', 'Y');
insert into ZHJDKP_CODE_TABLES (ID, TYPEID, VALUE, CODE, YXBZ)
values (34, 6, 'modal', '02', 'Y');
早年开发时,由于没有使用框架,纯碎的jdbc操作,要写大量的sql语句(排序关键字 order by 字段名1,字段名2,字段名N),然后组装返回数据给前台页面(当时主流还是xml格式的数据)
第二种:通过java自身的机制(记住,要是数据源是从数据库检索出来的,sql语句就不需要order by了,排序让java处理)
2.1. 单列排序
首先从数据库或其他源捞出数据映射出java集合模型,然后通过实现Comparator编写排序规则。
如下:模型类(就简单写了)
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/*
* Order class is a domain object which implements
* Comparable interface to provide sorting on the natural order.
* Order also provides couple of custom Comparators to
* sort object based upon amount and customer
*/
public class Order implements Comparable<Order> {
private int orderId;//订单id号
private String customer;//顾客名
private int amount;//此订单消费总额
public Order(int orderId, String customer, int amount) {
this.orderId = orderId;
this.customer = customer;
this.amount = amount;
}
public int getAmount() {return amount; }
public void setAmount(int amount) {this.amount = amount;}
public String getCustomer() {return customer;}
public void setCustomer(String customer) {this.customer = customer;}
public int getOrderId() {return orderId;}
public void setOrderId(int orderId) {this.orderId = orderId;}
/*
* Comparator implementation to Sort Order object based on Amount
*/
public static class OrderByAmount implements Comparator<Order> {
@Override
public int compare(Order o1, Order o2) {
return o1.amount > o2.amount ? 1 : (o1.amount < o2.amount ? -1 : 0);
}
}
/*
* Anohter implementation or Comparator interface to sort list of Order object
* based upon customer name.
*/
public static class OrderByCustomer implements Comparator<Order> {
@Override
public int compare(Order o1, Order o2) {
return o1.customer.compareTo(o2.customer);
}
}
/*
* Sorting on orderId is natural sorting for Order.
*/
@Override
public int compareTo(Order o) {
return this.orderId > o.orderId ? 1 : (this.orderId < o.orderId ? -1 : 0);
}
/*
* implementing toString method to print orderId of Order
*/
@Override
public String toString(){
return String.valueOf(orderId);//+"-"+customer+"-"+amount;
}
}
然后测试
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* @author dgm
* @describe "比较自定义类"
* @date 2020年11月26日
*/
public class ObjectSortingTest {
public static void main(String args[]) {
//Creating Order object to demonstrate Sorting of Object in Java
Order order1 = new Order(101,"zhangsan",100);
Order order2 = new Order(201,"wangwu",199);
Order order3 = new Order(301,"maliu",88);
Order order4 = new Order(401,"dgm",555);
Order order5 = new Order(501,"dongguangming",666);
//putting Objects into Collection to sort
//捞数据(不管从什么地方,实际上从数据库检索的情况多,主意此处的sql和第一种方式不同,sql不需要order by,排序在java代码中体现),由于是演示,就手工打造了
List<Order> orderList = new ArrayList<Order>();
orderList.add(order3);
orderList.add(order1);
orderList.add(order2);
orderList.add(order5);
orderList.add(order4);
//printing unsorted collection
System.out.println("未排序的列表 : " + orderList);
//Sorting Order Object on natural order - ascending
Collections.sort(orderList);
//printing sorted collection
System.out.println("自然排序(compareTo方法): " + orderList);
// Sorting object in descending order in Java
Collections.sort(orderList, Collections.reverseOrder());
System.out.println("反向排序 : " + orderList);
//Sorting object using Comparator in Java
Collections.sort(orderList, new Order.OrderByAmount());
System.out.println("根据传的排序规则,通过订单消费额 : " + orderList);
// Comparator sorting Example - Sorting based on customer
Collections.sort(orderList, new Order.OrderByCustomer());
System.out.println("根据传的排序规则,通过顾客名 : : " + orderList);
}
}
运行效果:
当然可以用匿名类实现或java8的语法(Lambda表达式)实现,简洁明了
//java8语法:Lambda表达式 Comparator sorting Example - Sorting based on customer
Collections.sort(orderList, (o1, o2) -> o1.getCustomer().compareTo(o2.getCustomer()));
System.out.println("根据传的排序规则,通过顾客名(比较规则由java8语法:Lambda表达式写) : : " + orderList);
2.2 多列排序
很多时候排序字段是多个,比如先按顾客名,然后再按消费额。
又添加了两条数据,方便测试排序
Order order1 = new Order(101,"zhangsan",100);
Order order2 = new Order(201,"wangwu",199);
Order order3 = new Order(301,"maliu",88);
Order order4 = new Order(401,"dgm",555);
Order order5 = new Order(501,"dongguangming",666);
Order order6 = new Order(601,"dgmaaa",444);
Order order7 = new Order(701,"wangsanniang",49);
//按多列排序
orderList.sort(Comparator.comparing(Order::getCustomer)
.thenComparing(Order::getAmount));
System.out.println("排序订单,多个字段 (先按顾客名后按消费额): " + orderList);
输出结果:
第三种: 通过前端JavaScript排序数据
比如后台接口返回给前端json,大致如下:
responseData= {
state :200,
data: [
{ name: "dgm", born: 1989},
{ name: "董广明", born: 1989 },
{ name: "dongguangming", born: 1989},
{ name: "王五", born: 1948 },
{ name: "bcd", born: 1995},
{ name: "xyz", born: 2000}
]
}
function compare(a, b) {
const nameA = a.name.toUpperCase();
const nameB = b.name.toUpperCase();
let comparison = 0;
if (nameA > nameB) {
comparison = 1;
} else if (nameA < nameB) {
comparison = -1;
}
return comparison;
}
console.log(responseData.data.sort(compare));
后记:排序选择(至于排序算法规则依需求而定)依实际情况而定。
总结: java特性越来越多了,简洁化代码开发,泛型、lambda表达式、并发包、stream等都是在新jdk版本引入,当然也有针对JVM改进优化,随着时代前进,java会更强大,引进更多的特性,当然jdk工具包也越来越大(记得早年用的jdk不到50m,而如今两百多兆空间就没了,一旦运行起来占得更多),应用程序也越来越大,物理设施(带宽(再牛逼的码农也难写出高并发大流量程序)、存储、内存(服务器才4g))不像以前是问题了,有多少资源就吃掉(比如redis、spark吃内存)、视频耗流量、图像天体计算吃cpu,所以你要大胆的想象怎么榨干资源。
参考:
-
A Beginner’s Guide to the True Order of SQL Operations https://blog.jooq.org/2016/12/09/a-beginners-guide-to-the-true-order-of-sql-operations/
-
How to Think Like the SQL Server Engine: Adding an ORDER BY https://www.brentozar.com/archive/2019/10/how-to-think-like-the-sql-server-engine-adding-an-order-by/
Sorting and Grouping https://use-the-index-luke.com/sql/sorting-grouping-
Java Lambda Expressions https://soshace.com/java-lambda-expressions/
-
6 Advanced Comparator and Comparable Examples in Java 8 for Sorting Objects https://www.java67.com/2019/06/top-5-sorting-examples-of-comparator-and-comparable-in-java.html#ixzz6f2fYAOL0
-
How to sort an array of objects in JavaScript
https://www.educative.io/edpresso/how-to-sort-an-array-of-objects-in-javascript
-
Quick Tip: How to Sort an Array of Objects in JavaScript https://www.sitepoint.com/sort-an-array-of-objects-in-javascript/