2017-08-09 34 views
1

我正在嘗試使用自定義比較器實現NavigableMap,該比較基於值而不是按鍵進行比較。我非常瞭解java和一般編碼,所以如果我的術語是inccorect或代碼可怕,請原諒我!我試圖尋找類似的問題,試圖複製解決方案,但我仍然recieving以下錯誤,當我嘗試編譯:NavigableMap - 基於值進行比較

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[]>) 

我想實現以下內容,其中浮法[]爲4個float數組[ 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; 
} 

我甚至不確定這是否是最好的方法來做到這一點,或者如果這是甚至可能,所以任何援助非常感謝。

+0

「比較器」用於比較*鍵*,因此'OrderLineSegments'需要實現'比較器'。因此,當您嘗試比較Map.Entry時出錯。 – Kayaman

+0

錯誤似乎很正常,因爲文檔說:'TreeMap的構造函數需要比較器',並且您提供了一個'比較器>'它不能像,不能反轉鍵和值嗎?如果您沒有相同的值,則可能會更改 – azro

+0

您正在違反NavigableMap的合同。爲什麼不在這種情況下使用排序列表? – daniu

回答

0

您可以使用支持映射創建比較器作爲單獨的對象,然後在比較方法中獲取來自同一映射的值。在此之後,您可以將您的邏輯應用到值... 您還需要使用覆蓋的「放置」方法擴展樹圖,該方法將內容放入支持地圖中,然後將其放入實際的可導航地圖。

這些方針的東西:

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] 

雖然這種解決方案是令人費解的和醜陋的,它絕對應該工作。使用包含key和value的對象的樹集更自然,然後使用您的問題中提出的實現邏輯爲其創建自定義比較器。

+0

謝謝!現在正在編譯。 儘管地圖的排序似乎並未服從比較函數。 例如: 如果地圖已包含:1.3283:1.3283,89.719,5.7766,70.22] 我補充一下:3.2011:3.2011,72.564,14.316,55.937] 應該插入到左邊(即較低的位置)並且看起來像: {3.2011:[3.2011,72.564,14.316,55.937],1.3283:[1.3283,89.719,5.7766,70.22]} 但它被添加到右邊(上位置)像這個: {1.3283:[1.3283,89.719,5.7766,70.22],3.2011:[3.2011,72.564,14.316,55.937]} – fortymod

+0

看來比較沒有被調用。我在比較塊中放置了一條println語句,沒有打印任何內容。我認爲這表明它沒有被使用,並且正在使用自然鍵順序?我還需要做些什麼才能實現? – fortymod

+0

我的歉意,確實如此。我已經更新了答案。你能再次嘗試一下代碼嗎?請讓我知道,如果它適合你。 –