使用将 Comparator 作为参数实现的 class 的问题
Problems using a class that implements Comparator as a parameter
我有一张地图需要根据非常具体的条件进行排序,所以我创建了以下 class:
private class EventComparator implements Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>> {
Crew crew;
public EventComparator(Crew crew) {
this.crew = crew;
}
@Override
public int compare(java.util.Map.Entry<Event, Entry> o1,
java.util.Map.Entry<Event, Entry> o2) {
// algorithm for comparing
}
}
然后我创建了一个单独的静态 class 和将使用冒泡排序的函数:
public static <K, V> void mapSort(LinkedHashMap<K, V> map,
Comparator<Map.Entry<? super K, ? super V>> comparator) {
// array list is more efficient
ArrayList<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
int i; // var for iterating
boolean swap = true; // false if no swaps occurred (list is sorted)
Map.Entry<K, V> temp;
while(swap) {
swap = false; // assume no swap will occur
for (i = 0; i < entries.size() -1; i++)
if (comparator.compare(entries.get(i), entries.get(i + 1)) > 0) {
temp = entries.get(i);
entries.set(i, entries.get(i + 1));
entries.set(i + 1, temp);
swap = true;
}
}
// re-factor the original map
map.clear();
for (Map.Entry<K, V> entry : entries)
map.put(entry.getKey(), entry.getValue());
}
需要注意的重要一点是函数采用的参数。我以为我可以简单地执行以下操作: mapSort(sorted, new EventComparator(crew))
但 Eclipse 警告我第二个参数的类型不正确。关于如何实现这一点有什么建议吗?
应 Tim 的要求,这是调用它的代码:
// Reduce team size if necessary
if (crew.getSize() > 15) {
System.out.println("Crew reduction neccessary"); // DEBUG
// get list of the next step down in feeder
LinkedHashMap<Event, gohs.scyoly.core.Entry> sorted = new LinkedHashMap<>(feeder.size());
for (Map.Entry<Event, Stack<Entry>> feederEntry : feeder.entrySet()) {
sorted.put(feederEntry.getKey(), feederEntry.getValue().peek());
}
BubbleSort.mapSort(sorted, new EventComparator(crew));
System.out.println(sorted.entrySet()); // DEBUG
}
对于上下文,该应用程序旨在扫描团队分数以查找事件,这些分数存储为条目,然后输出完美的 "crew",这是一起参加事件的团队的集合。
更新:
我将代码更改为以下内容:
BubbleSort.mapSort(sorted, (Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>>) new EventComparator(crew));
但它仍然给我一个错误消息:
The method mapSort(LinkedHashMap<K,V>, Comparator<Map.Entry<? super K,? super V>>) in the type Assembler.BubbleSort is not applicable for the arguments (LinkedHashMap<Event,Entry>, Comparator<Map.Entry<Event,Entry>>)
[从我的评论中复制]
对于 sortMap 的签名,将 Comparator<Map.Entry<? super K, ? super V>>
更改为 Comparator<Map.Entry<K, V>>
。只是开始,我总是难以全神贯注(super
vs extends
)。
[更新]
Effective Java,第 2 版:"Item 28: Use bounded wildcards to increase API flexibility" 中有一个关于 <? super XXX>
和 <? extends XXX>
的很好的部分,特别是他们谈论 'PECS' 的地方 -生产者扩展,消费者超级。
我仍然需要更好地研究这种情况下的原因,但至少我们有了一个起点。
Comparator<Map.Entry<Event,Entry>>
不是Comparator<Map.Entry<? super K, ? super V>>
的子类型,因为Comparator
的类型参数不同。就像 List<String>
不是 List<Object>
的子类型一样,因为 String
和 Object
是不同的,即使 String
是 Object
的子类型.
如果要对 Map.Entry
的参数使用通配符,则还需要在 Comparator
的参数级别使用通配符,如下所示:
Comparator<? extends Map.Entry<? super K, ? super V>>
我有一张地图需要根据非常具体的条件进行排序,所以我创建了以下 class:
private class EventComparator implements Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>> {
Crew crew;
public EventComparator(Crew crew) {
this.crew = crew;
}
@Override
public int compare(java.util.Map.Entry<Event, Entry> o1,
java.util.Map.Entry<Event, Entry> o2) {
// algorithm for comparing
}
}
然后我创建了一个单独的静态 class 和将使用冒泡排序的函数:
public static <K, V> void mapSort(LinkedHashMap<K, V> map,
Comparator<Map.Entry<? super K, ? super V>> comparator) {
// array list is more efficient
ArrayList<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
int i; // var for iterating
boolean swap = true; // false if no swaps occurred (list is sorted)
Map.Entry<K, V> temp;
while(swap) {
swap = false; // assume no swap will occur
for (i = 0; i < entries.size() -1; i++)
if (comparator.compare(entries.get(i), entries.get(i + 1)) > 0) {
temp = entries.get(i);
entries.set(i, entries.get(i + 1));
entries.set(i + 1, temp);
swap = true;
}
}
// re-factor the original map
map.clear();
for (Map.Entry<K, V> entry : entries)
map.put(entry.getKey(), entry.getValue());
}
需要注意的重要一点是函数采用的参数。我以为我可以简单地执行以下操作: mapSort(sorted, new EventComparator(crew))
但 Eclipse 警告我第二个参数的类型不正确。关于如何实现这一点有什么建议吗?
应 Tim 的要求,这是调用它的代码:
// Reduce team size if necessary
if (crew.getSize() > 15) {
System.out.println("Crew reduction neccessary"); // DEBUG
// get list of the next step down in feeder
LinkedHashMap<Event, gohs.scyoly.core.Entry> sorted = new LinkedHashMap<>(feeder.size());
for (Map.Entry<Event, Stack<Entry>> feederEntry : feeder.entrySet()) {
sorted.put(feederEntry.getKey(), feederEntry.getValue().peek());
}
BubbleSort.mapSort(sorted, new EventComparator(crew));
System.out.println(sorted.entrySet()); // DEBUG
}
对于上下文,该应用程序旨在扫描团队分数以查找事件,这些分数存储为条目,然后输出完美的 "crew",这是一起参加事件的团队的集合。
更新: 我将代码更改为以下内容:
BubbleSort.mapSort(sorted, (Comparator<Map.Entry<Event, gohs.scyoly.core.Entry>>) new EventComparator(crew));
但它仍然给我一个错误消息:
The method mapSort(LinkedHashMap<K,V>, Comparator<Map.Entry<? super K,? super V>>) in the type Assembler.BubbleSort is not applicable for the arguments (LinkedHashMap<Event,Entry>, Comparator<Map.Entry<Event,Entry>>)
[从我的评论中复制]
对于 sortMap 的签名,将 Comparator<Map.Entry<? super K, ? super V>>
更改为 Comparator<Map.Entry<K, V>>
。只是开始,我总是难以全神贯注(super
vs extends
)。
[更新]
Effective Java,第 2 版:"Item 28: Use bounded wildcards to increase API flexibility" 中有一个关于 <? super XXX>
和 <? extends XXX>
的很好的部分,特别是他们谈论 'PECS' 的地方 -生产者扩展,消费者超级。
我仍然需要更好地研究这种情况下的原因,但至少我们有了一个起点。
Comparator<Map.Entry<Event,Entry>>
不是Comparator<Map.Entry<? super K, ? super V>>
的子类型,因为Comparator
的类型参数不同。就像 List<String>
不是 List<Object>
的子类型一样,因为 String
和 Object
是不同的,即使 String
是 Object
的子类型.
如果要对 Map.Entry
的参数使用通配符,则还需要在 Comparator
的参数级别使用通配符,如下所示:
Comparator<? extends Map.Entry<? super K, ? super V>>