如何使用比较器对重复的字符串进行排序?
假设我有一个包含工人的列表,每个工人都有三个字段:名称,他所在的部门(可以只是部门的名称或班级部门的对象)和他的工资。
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 API:
方法iterator()中提供的Iterator不保证以任何特定顺序遍历优先级队列的元素。 如果您需要有序遍历,请考虑使用Arrays.sort(pq.toArray())。
不要使用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());
}
使用这个问题作为流/ 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));
链接地址: http://www.djcxy.com/p/40983.html