题干
假设有一外卖app,发现附近有5个店铺,店铺信息包括ld、评价得分(score) 、人均消费额(average) 、以及距离(distance) ,具体数据如下:
private static final List<Shop> shops = new ArrayList<Shop>() {{
add(new Shop(1, 9, 20.8, 5.6));
add(new Shop(2, 8, 14.0, 2.3));
add(new Shop(3, 4, 60.9, 8.1));
add(new Shop(4, 8, 20.8, 3.6));
add(new Shop(5, 6, 20.8, 3.6));
}};
请你使用java Comparator对这些商家进行内存排序,要求合理运用设计模式达到任意组合这三个维度及其升降序的目的(参考sql的多条件排序) ,入参为字符串,格式示例:sort=average&order=desc,sort=score&order=asc,sort=distance&order=asc。
允许输入一组或多组,多组排序条件用逗号隔开,sort指以哪个字段排序, order指升序还是降序,执行后输出店铺id的排列,并以中划线连接,如输入sort= score&order=desc,sort= average&order=asc,则输出1-2-4-5-3。
查找资料与思考
定义一系列的算法,把他们一个个封装起来,在使用他们的时候可以相互替换,并且不会影响到使用算法的客户端。
简单来说就是我们使用Collections.sort时就是将可能会变动的排序算法编入了不变的接口中,我们可以根据需求改动接口的内容,外界依然可以正常调用,同时也可以给不同类型数据提供服务。类似的,Comparator接口也是如此,简单思考应该能明白,也可以再找一些设计模式的博客或书籍补充一下相关知识(别像我一样凉掉)。
整体思路
-
根据需求创建自定义Comparator实现接口,既然有多个排序需求,自然要分别定义多个Comparator,有朋友和我交流时认为可以直接整合,但整合多条件判断会导致无法自由改变条件顺序,若有更好思路,网友可留下评论讨论。
static class ScoreAscComparator implements Comparator<Shop> { @Override public int compare(Shop o1, Shop o2) { return o1.score - o2.score; } } -
将输入字符串切分,转化为自定义数组,创建Comparator列表依次add自定义Comparator
String[] parameter = input.split(","); List<Comparator<Shop>> comparators = new ArrayList<>(); for (String s : parameter) { s = s.replaceAll("sort=|&order", ""); comparators.add(comparatorMap.get(s)); } -
对shops队列进行排序,return 0的位置蛮妙的,忘记哪篇博客学习到的这个技巧,远程向那位大佬致意了
shopsCopy.sort((o1, o2) -> { for (Comparator<Shop> comparator : comparators) { if (comparator.compare(o1, o2) < 0) { return -1; } else if (comparator.compare(o1, o2) > 0) { return 1; } } return 0; });gg -
根据要求输出,这就没什么好说的了
List<String> output = new ArrayList<>(); for (Shop shop : shopsCopy) { output.add(String.valueOf(shop.getId())); } System.out.println(StringUtils.join(output, "-"));
完整代码
public class Main {
static class Shop {
private int id;
private int score;
private double average;
private double distance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Shop() {
}
public Shop(int id, int score, double average, double distance) {
this.id = id;
this.score = score;
this.average = average;
this.distance = distance;
}
}
static class ScoreAscComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return o1.score - o2.score;
}
}
static class ScoreDescComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return o2.score - o1.score;
}
}
static class AverageAscComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return (int) (o1.average - o2.average);
}
}
static class AverageDescComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return (int) (o2.average - o1.average);
}
}
static class DistanceAscComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return (int) (o1.distance - o2.distance);
}
}
static class DistanceDescComparator implements Comparator<Shop> {
@Override
public int compare(Shop o1, Shop o2) {
return (int) (o2.distance - o1.distance);
}
}
private static final Map<String, Comparator<Shop>> comparatorMap = new HashMap<String, Comparator<Shop>>() {{
put("score=asc", new ScoreAscComparator());
put("score=desc", new ScoreDescComparator());
put("average=asc", new AverageAscComparator());
put("average=desc", new AverageDescComparator());
put("distance=asc", new DistanceAscComparator());
put("distance=desc", new DistanceDescComparator());
}};
private static final List<Shop> shops = new ArrayList<Shop>() {{
add(new Shop(1, 9, 20.8, 5.6));
add(new Shop(2, 8, 14.0, 2.3));
add(new Shop(3, 4, 60.9, 8.1));
add(new Shop(4, 8, 20.8, 3.6));
add(new Shop(5, 6, 20.8, 3.6));
}};
public static void main(String[] args) {
//输入值例:sort=average&order=desc,sort=score&order=asc,sort=distance&order=asc
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
//输入值处理为类键值对格式:score=asc
String[] parameter = input.split(",");
List<Comparator<Shop>> comparators = new ArrayList<>();
for (String s : parameter) {
s = s.replaceAll("sort=|&order", "");
comparators.add(comparatorMap.get(s));
}
List<Shop> shopsCopy = new ArrayList<>(Arrays.asList(new Shop[shops.size()]));
Collections.copy(shopsCopy, shops);
shopsCopy.sort((o1, o2) -> {
for (Comparator<Shop> comparator : comparators) {
if (comparator.compare(o1, o2) < 0) {
return -1;
} else if (comparator.compare(o1, o2) > 0) {
return 1;
}
}
return 0;
});
List<String> output = new ArrayList<>();
for (Shop shop : shopsCopy) {
output.add(String.valueOf(shop.getId()));
}
System.out.println(StringUtils.join(output, "-"));
}
}