实现一个重排算法:给定一个商品列表,商品上有id、类型和分数三个字段。对不同类型的商品按分数从高到低排序。要求排序前后对应类型在列表中的位置保持不变。
1、示例:
输入的商品列表如下:
[10011,1,70]
[91011,2,90]
[20011,2,60]
[30011,1,50]
[40011,1,10]
[15011,2,20]
[16011,1,30]
[80011,2,80]
[90011,1,15]
类型为1的商品有5个,排序结果为:[10011,1,70],[30011,1,50],[16011,1,30],[90011,1,15],[40011,1,10]
类型为2的商品有4个,排序结果为:[91011,2,90],[80011,2,80],[20011,2,60],[15011,2,20]
排序前类型为1的商品在列表中的位置为1,4,5,7,9,排序后这几个位置仍然放类型为1的商品,其他类型规则类似。
输出的商品列表如下:
[10011,1,70]
[91011,2,90]
[80011,2,80]
[30011,1,50]
[16011,1,30]
[20011,2,60]
[90011,1,15]
[15011,2,20]
[40011,1,10]
2、说明
(1)元素个数不会太多,不用考虑商品列表中元素个数过多的情况
(2)商品的具体类型不确定,只知道不超过5种类型
(3)商品的分数为double类型,取值为[0,100]
(4)要求至少使用一项多线程技术,重点考核本项
package com.jTest.leet;
import cn.hutool.core.collection.CollectionUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
public class ItemRerank {
static ExecutorService threadPoolExecutor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws InterruptedException{
ItemDO itemDO_ = new ItemDO(1,1,80);
ItemDO itemDO = new ItemDO(2,2,80);
ItemDO itemDO2 = new ItemDO(3,1,70);
ItemDO itemDO3 = new ItemDO(4,1,90);
List<ItemDO> list = new ArrayList<>();
list.add(itemDO);
list.add(itemDO2);
list.add(itemDO3);
list.add(itemDO_);
System.out.println(list);
System.out.println(rerank(list));
}
public static List<ItemDO> rerank(List<ItemDO> itemList) throws InterruptedException {
ItemDO[] result = new ItemDO[itemList.size()];
if(CollectionUtil.isEmpty(itemList)){
return Arrays.asList(result);
}
//用来类型存放数组线标
Map<Integer,Set<Integer>> typeMap = getTypeMap(itemList);
CountDownLatch downLatch = new CountDownLatch(typeMap.size());
Set<Map.Entry<Integer, Set<Integer>>> entries = typeMap.entrySet();
for ( Map.Entry<Integer, Set<Integer>> entry : entries) {
threadPoolExecutor.submit(() -> {
Set<Integer> indexSet = entry.getValue();
List<ItemDO> itemDOS = new ArrayList(indexSet.size());
for (Integer index : indexSet) {
itemDOS.add(itemList.get(index));
}
List<ItemDO> sortList = itemDOS.stream().sorted((o1,o2)-> - Double.compare(o1.score,o2.score)).collect(Collectors.toList());
int index_ = 0;
for (Integer index : indexSet) {
result[index] = sortList.get(index_);
index_++;
}
downLatch.countDown();
System.out.println("222222");
});
}
//或者自行捕获异常
downLatch.await();
return Arrays.asList(result);
}
/**
* 映射好对应的类型和类型对应的位置
* @param itemList
* @return
*/
private static Map<Integer, Set<Integer>> getTypeMap(List<ItemDO> itemList) {
Map<Integer, Set<Integer>> typeMap = new HashMap<>(itemList.size()/2);
for (int i = 0; i < itemList.size(); i++) {
Integer type = itemList.get(i).getType();
if(typeMap.containsKey(type)){
//已存在对应类型则进行add
typeMap.get(type).add(i);
}else {
//不存在则进行put
Set<Integer> list = new TreeSet<>();
list.add(i);
typeMap.put(type,list);
}
}
return typeMap;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
static class ItemDO {
private long id;
private int type;
private double score;
}
}