我正在尝试使用自定义比较器实现一个可导航映射,该比较器根据值而不是键进行比较。我对Java和编码非常了解,所以如果我的术语不合时宜或代码很糟糕,请原谅我!我尝试寻找类似的问题来尝试复制解决方案,但在尝试编译时仍然收到以下错误:
java: no suitable constructor found for TreeMap(OrderLineSegments)
constructor java.util.TreeMap.TreeMap(java.util.Comparator<? super java.lang.Float>) is not applicable
(argument mismatch; OrderLineSegments cannot be converted to java.util.Comparator<? super java.lang.Float>)
constructor java.util.TreeMap.TreeMap(java.util.Map<? extends java.lang.Float,? extends java.lang.Float[]>) is not applicable
(argument mismatch; OrderLineSegments cannot be converted to java.util.Map<? extends java.lang.Float,? extends java.lang.Float[]>)
constructor java.util.TreeMap.TreeMap(java.util.SortedMap<java.lang.Float,? extends java.lang.Float[]>) is not applicable
(argument mismatch; OrderLineSegments cannot be converted to java.util.SortedMap<java.lang.Float,? extends java.lang.Float[]>)
我正在尝试实现以下内容,其中 Float[] 是代表线段的 4 个浮点数 [x1,y1,x2,y2] 的数组。
NavigableMap<Float, Float[]> segmentBST = new TreeMap<Float, Float[]>( new OrderLineSegments() );
class OrderLineSegments implements Comparator<Map.Entry<Float, Float[]>> {
public int compare(Map.Entry<Float, Float[]> a, Map.Entry<Float, Float[]> b) {
float ypos;
if (a.getValue()[1] < a.getValue()[1]) {
ypos = a.getValue()[1];
} else {
ypos = b.getValue()[1];
}
float ratioA = (a.getValue()[1] - ypos) / (ypos - a.getValue()[3]);
float ratioB = (b.getValue()[1] - ypos) / (ypos - b.getValue()[3]);
float posA = Math.abs(a.getValue()[0] - a.getValue()[2]) * ratioA + a.getValue()[0];
float posB = Math.abs(b.getValue()[0] - b.getValue()[2]) * ratioB + b.getValue()[0];
if (posA < posB) return 1;
if (posA > posB) return -1;
return 0;
}
我什至不确定这是否是最好的方法,或者这是否可能,因此非常感谢任何帮助。
您可以将比较器创建为具有支持映射的单独对象,然后在比较方法中从同一映射中获取值。在此之后,您可以将逻辑应用于值... 您还需要使用树形图的扩展和重写的"put"方法,该方法将内容放入支持地图中,然后再将其放入实际的可导航地图中。
大致如下:
public static void main(String[] args) throws IOException {
// Sun, 27 Jul 2014 10:19:10 +0100
class OrderLineSegments implements Comparator<Float> {
private Map<Float, Float[]> supportMap = new HashMap<>();
public int compare(Float aKey, Float bKey) {
Float[] aValue = supportMap.get(aKey);
Float[] bValue = supportMap.get(bKey);
float ypos;
if (aValue[1] < bValue[1]) {
ypos = aValue[1];
} else {
ypos = bValue[1];
}
float ratioA = (aValue[1] - ypos) / (ypos - aValue[3]);
float ratioB = (bValue[1] - ypos) / (ypos - bValue[3]);
float posA = Math.abs(aValue[0] - aValue[2]) * ratioA + aValue[0];
float posB = Math.abs(bValue[0] - bValue[2]) * ratioB + bValue[0];
if (posA < posB) return 1;
if (posA > posB) return -1;
return 0;
}
}
OrderLineSegments orderLineSegments = new OrderLineSegments();
class ExtendendNavigableMap extends TreeMap<Float, Float[]> {
private OrderLineSegments orderLineSegments;
public ExtendendNavigableMap(OrderLineSegments comparator) {
super(comparator);
orderLineSegments = comparator;
}
@Override
public Float[] put(Float key, Float[] value) {
orderLineSegments.supportMap.put(key, value);
return super.put(key, value);
}
}
NavigableMap<Float, Float[]> segmentBST = new ExtendendNavigableMap(orderLineSegments);
// Start adding elements
segmentBST.put(1.0F, new Float[]{0.1f, 0.2f, 0.3f, 0.4f});
segmentBST.put(1.9F, new Float[]{0.3f, 0.2f, 0.3f, 0.4f});
segmentBST.put(1.1F, new Float[]{-0.3f, 0.2f, 0.3f, 0.4f});
segmentBST.forEach((k, v) -> System.out.printf("%s:%s%n", k, Arrays.toString(v)));
}
输出:
1.9:[0.3, 0.2, 0.3, 0.4]
1.0:[0.1, 0.2, 0.3, 0.4]
1.1:[-0.3, 0.2, 0.3, 0.4]
虽然这个解决方案令人费解且丑陋,但它绝对应该有效。更自然的做法是使用树集和一个同时包含键和值的对象,然后使用您的问题中建议的实现逻辑为其创建自定义比较器。