如何为TreeMap编写客户equalsTo / compareTo / hasCode以获得前N个值

问题描述

问题是:
客户希望查看到目前为止最畅销的商品。我们希望将这些数据有效地提供给我们的客户。
样品输入:
已售商品清单:
F | 400
B | 1000
A | 500
A | 600
C | 1000
D | 700
E | 300
样品输出
A | 1100
C | 1000
B | 1000
D | 700

我的想法是在第一个API processinput()中,使用商品和价值的映射来跟踪到目前为止已售出的所有商品,然后将更新后的商品添加到最大优先级队列中。在第二个API processQuery()中,只需从队列中选择前K个即可。 processQuery中存在一个问题,时间复杂度为O(NlogN)

我们是否可以通过覆盖TreeMap而用单个equalsTo解决此问题, 'comparetohasCode,以便该树图按值排序。因此,我们只是遍历TreeMap并返回topN个项目?

解决方法

假定输入是上述格式的字符串列表,第一步type Maybe<T> = T | null; const sayHelloTo = (str: string) => console.log(`hello ${str}`); function myFunc( x: string[] ) { x.forEach(item => sayHelloTo(item)) } const x = ['abc',null,'xyz'] as Maybe<string>[]; const newX = x.filter(item => item !== null); // Error: newX still type Maybe<string>[] does not match the expected <string>[] myFunc(newX); 是将输入列表转换为某些对象{name,num}的列表:

processInput

然后,第二种方法按名称分组,对总值求和,并返回类似的结果列表:

public static List<Obj> processInput(List<String> data) {
    return Arrays.stream(data)
                 .map(s -> s.split("\\|"))
                 .map(arr -> new Obj(arr[0],Integer.parseInt(arr[1])))
                 .collect(Collectors.toList());
}
,

您需要在两个方向上进行有效访问:项目到达时,您需要根据其名称(A,B,C)获得汇总金额,但是要对它们进行排序,将使用汇总金额。我认为您可以使用Map来按名称查找项目,并使用SortedSet进行排序。由于金额本身不是唯一的(例如B和C在示例中均为1000),因此排序也应使用名称(因为它们是唯一的),这就是为什么一组足以满足该需求的原因:

import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

public class Test {
    static class Item implements Comparable<Item> {
        final String name;
        int amount;
        Item(String name,int amount){
            this.name=name;
            this.amount=amount;
        }
        public int compareTo(Item o) {
            if(o.amount<amount)
                return -1;
            if(o.amount>amount)
                return 1;
            return o.name.compareTo(name);
        }
        public String toString() {
            return name+"|"+amount;
        }
    }
    
    Map<String,Item> itemmap=new HashMap<>();
    SortedSet<Item> sorted=new TreeSet<>();
    
    void add(String name,int amount) {
        Item i=itemmap.get(name);
        if(i!=null) {
            sorted.remove(i);
            i.amount+=amount;
        } else {
            i=new Item(name,amount);
        }
        itemmap.put(name,i);
        sorted.add(i);
    }
    public static void main(String[] args) {
        Test t=new Test();
        t.add("F",400);
        t.add("B",1000);
        t.add("xA",500);
        t.add("xA",600);
        t.add("C",1000);
        t.add("D",700);
        t.add("E",300);
        System.out.println("itemmap: "+t.itemmap);
        System.out.println("sorted: "+t.sorted);
    }
}

它产生输出(在Ideone上测试:https://ideone.com/2d79aC

itemmap: {B=B|1000,C=C|1000,D=D|700,E=E|300,F=F|400,xA=xA|1100}
sorted: [xA|1100,C|1000,B|1000,D|700,F|400,E|300]

我故意将A重命名为xA,否则映射将为A|1100,C|1000,但这只是字母顺序的巧合(散列了几个连续的单字母字符串实际上并没有混合订单)。 C和B的顺序相反,因为这就是您要的。如果您希望它们为B,然后为C,则交换compareTo(),或仅返回当前的负号。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...