NavigableMap - 基于值进行比较

时间:2017-08-09 12:49:55

标签: java dictionary compare comparator

我正在尝试使用自定义比较器实现NavigableMap,该比较器基于值而不是键进行比较。我非常非常了解java和编码,所以如果我的术语是inccorect或代码可怕请原谅我!我试图找到类似的问题来尝试复制解决方案,但在我尝试编译时仍然收到以下错误:

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

我甚至不确定这是否是最好的方式,或者如果这是可能的,所以非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

您可以将比较器创建为具有支持贴图的单独对象,然后在compare方法中获取同一贴图中的值。在此之后,您可以将您的逻辑应用于值... 您还需要使用树图的扩展名和覆盖的“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]

虽然这个解决方案令人费解和丑陋,但它绝对有效。使用包含键和值的对象的树集更自然,然后使用您的问题中建议的实现逻辑为它创建自定义比较器。