【问题标题】:How to sort duplicated Strings using comparator?如何使用比较器对重复的字符串进行排序?
【发布时间】:2017-12-14 12:13:40
【问题描述】:

假设我有一个包含工人的列表,每个工人有 3 个字段:它的名称、他所在的部门(可以只是部门的名称或类部门中的一个对象)和他的薪水。

Elvis       Software Engineering        1000
Samba       Mechanical Engineering      2000
Bamba       Industrial Engineering      3000
Bisli       Medical Engineering         4000
Kinder      Electrical Engineering      1000
Elvis       Software Engineering        9999

现在我想按名称对它们进行排序并将结果放入队列中。 然后将队列放在地图中,从底部到顶部排序 所以排序后我想要的结果是:

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(),所以我使用了一个比较器,它按工人的姓名对他们进行排序,如果姓名相同 - 它按部门排序,如果部门相同 - 它按工资排序。 这是我写的比较器:

    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();

    }
}

问题是结果是这样的:

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(重复的)未排序,它停留在队列的末尾。我尝试用另一个重复的名称替换猫王,结果相同。 我错过了什么?我如何对重复值进行排序,以便它们一个接一个? 代码如下:

    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;
}

【问题讨论】:

  • 为什么要使用 PriorityQueue?如果您希望数据结构使用该比较器为您排序元素,请使用TreeSet
  • 这个类及其迭代器实现了 Collection 和 Iterator 接口的所有可选方法。方法 iterator() 中提供的 Iterator 不能保证以任何特定顺序遍历优先级队列的元素。如果您需要有序遍历,请考虑使用 Arrays.sort(pq.toArray())。参考文档:docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html

标签: java sorting queue comparator treemap


【解决方案1】:

PriorityQueue API:

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

【讨论】:

    【解决方案2】:

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

    // 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());
    }
    

    【讨论】:

    • 谢谢大家,我使用 TreeSet 并在比较器中定义如果工人相同,则认为其中一个更大。
    【解决方案3】:

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

    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));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-21
      • 1970-01-01
      • 2014-04-14
      相关资源
      最近更新 更多