阿里拍卖面试题:实现一个重拍序

实现一个重排算法:给定一个商品列表,商品上有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;

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值