首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用比较器对重复字符串进行排序?

如何使用比较器对重复字符串进行排序?
EN

Stack Overflow用户
提问于 2017-12-14 20:13:40
回答 3查看 139关注 0票数 7

假设我有一个包含工人的列表,每个工人都有3个字段:其名称、他所在的部门(可以是部门的名称或来自类department的对象)和他的工资。

代码语言:javascript
复制
Elvis       Software Engineering        1000
Samba       Mechanical Engineering      2000
Bamba       Industrial Engineering      3000
Bisli       Medical Engineering         4000
Kinder      Electrical Engineering      1000
Elvis       Software Engineering        9999

现在,我想按它们的名称对它们进行排序,并将结果放入队列中。然后把队列放在一个映射中,从下到上排序,所以排序后我想要的结果是:

代码语言:javascript
复制
Bamba       Industrial Engineering      3000
Bisli       Medical Engineering         4000
Elvis       Software Engineering        1000
Elvis       Software Engineering        9999
Samba       Mechanical Engineering      2000
Kinder      Electrical Engineering      1000

我不允许使用Collection.sort(),所以我使用了一个比较器,它按工人的姓名排序,如果姓名相等,则按部门排序,如果部门相等,则按工资排序。这是我写的比较器:

代码语言:javascript
复制
    class WorkerComparatorByName implements Comparator<Worker<?>> {
    @Override
    public int compare(Worker<?> w1, Worker<?> w2) {
        int compareValue = w1.getName().compareTo(w2.getName());
        if (compareValue != 0)
            return compareValue;
        compareValue = w1.getDepartment().toString().compareTo(w2.getDepartment().toString());
        if (compareValue != 0)
            return compareValue;
        return w1.getSalary() - w2.getSalary();

    }
}

问题是结果是这样的:

代码语言:javascript
复制
Bamba       Industrial Engineering      3000
Bisli       Medical Engineering         4000
Elvis       Software Engineering        1000
Samba       Mechanical Engineering      2000
Kinder      Electrical Engineering      1000
Elvis       Software Engineering        9999

对所有工作进程进行排序,但不对Elvis (重复的)进行排序,它停留在队列的末尾。我试着用另一个重复的名字替换Elvis,结果是一样的。我遗漏了什么?我如何对重复的值进行排序,使它们一个接一个地排序?代码如下:

代码语言:javascript
复制
    public <T extends Worker<?>> Map<?, ?> createMap(ArrayList<T> list) {
    int i = 1;
    // creating a PriorityQueue sorted by names
    Queue<T> pq = new PriorityQueue<>(new WorkerComparatorByName());
    // filling the PriorityQueue with the workers
    pq.addAll(list);
    Map<Integer, T> treeMap = new TreeMap<Integer, T>();
    // iterating over the PriorityQueue and puting the workers in the map
    for (T element : pq)
        treeMap.put(i++, element);
    return treeMap;
}
EN

回答 3

Stack Overflow用户

发布于 2017-12-14 20:34:56

PriorityQueue接口:

方法iterator()中提供的Iterator不能保证以任何特定的顺序遍历优先级队列的元素。如果需要有序遍历,可以考虑使用Arrays.sort(pq.toArray())。

票数 2
EN

Stack Overflow用户

发布于 2017-12-14 21:14:39

不使用foreach循环,而是使用普通的for循环并poll()队列中的项。

代码语言:javascript
复制
// creating a PriorityQueue sorted by names
Queue<T> pq = new PriorityQueue<>(new WorkerComparatorByName());

// filling the PriorityQueue with the workers
pq.addAll(list);

Map<Integer, T> treeMap = new TreeMap<Integer, T>();

int size = pq.size();
for (int j = 0; j < size; j++) {
        treeMap.put(j + 1, pq.poll());
}
票数 1
EN

Stack Overflow用户

发布于 2017-12-15 04:07:26

使用了这个问题作为流/λ练习,还使用了一些Java8 comparing的好东西。我看到您最终使用了TreeSet,这是一个很好的解决方案,但如果有人感兴趣的话,我还是会添加这个。

代码语言:javascript
复制
PriorityQueue<Worker> queue =
        new PriorityQueue<>(Comparator.comparing(Worker::getName)
                                    .thenComparing(Worker::getDepartment)
                                    .thenComparing(Worker::getSalary));
queue.addAll(list);

TreeMap<Integer, Worker> treeMap =
        IntStream.range(1, queue.size() + 1)
                .boxed()
                .collect(Collectors.toMap(Function.identity(),
                                          o -> queue.poll(),
                                          (u, v) -> { throw new Error("Will never happen"); },
                                          TreeMap::new));
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47813127

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档