2016-02-02 2 views
3

редактировать - несколько упрощенный пример ниже (любой проще, и я не уверен, что она содержит все элементы желаемого поведения)Java компаратор, Сопоставимые и TreeSet.contains

Ниже приведен фрагмент кода, который представляет собой одна вещь, которую я пытаюсь сделать с компаратором. Я хотел бы, содержит вернуть true раз во второй раз, что doRSM называется:

package comparisonTest; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Comparator; 
import java.util.HashMap; 
import java.util.Iterator; 
import java.util.Map; 
import java.util.PriorityQueue; 
import java.util.SortedSet; 
import java.util.TreeSet; 

public class ComparisonTest { 

    private static class ArbitraryItem { 
     String node; 
     ArbitraryItem(String node) { 
      this.node = node; 
     } 
     public String getNode() { 
      return node; 
     } 
    } 

    private static final Map<String, ResultSet> idToArbitraryItems = new HashMap<>(); 


    private static class ArbitraryItemComparable implements Comparable<ArbitraryItemComparable> { 
     ArbitraryItem item; 
     Comparator<ArbitraryItemComparable> c; 
     ArbitraryItemComparable(ArbitraryItem item, Comparator<ArbitraryItemComparable> c) { 
      this.item = item; 
      this.c = c; 
     } 
     @Override 
     public boolean equals(Object o) { 
      if (!(o instanceof ArbitraryItemComparable)) { 
       System.out.println("not a ArbitraryItemComparable="+o); 
       return false; 
      } 
      boolean eq = this.c.compare(this, ((ArbitraryItemComparable)o)) == 0; 
      System.out.println(" equality val="+eq); 
      return eq; 
     } 
     @Override 
     public int compareTo(ArbitraryItemComparable o) { 
      int compVal = this.c.compare(this, ((ArbitraryItemComparable)o)); 
      System.out.println(" comparison val="+compVal); 
      return compVal; 
     } 

    } 

    private static class ResultSet { 
     SortedSet<ArbitraryItemComparable> usedResults; 
     String node; 
     Comparator<ArbitraryItemComparable> comparator; 
     ResultSet(String node, Comparator<ArbitraryItemComparable> comparator) { 
      this.usedResults = new TreeSet<ArbitraryItemComparable>(); 
      this.node = node; 
      this.comparator = comparator; 
     } 
    } 

    static private void doRSM(Collection <ArbitraryItem> foobar, ResultSet set, int max, boolean close, String id) { 
     Iterator<ArbitraryItem> items = foobar.iterator(); 
     for (;items.hasNext();) { 
      ArbitraryItem item = (ArbitraryItem) items.next(); 
      ArbitraryItemComparable itemComparable = new ArbitraryItemComparable(item, set.comparator); 
      System.out.println("*** looking at node "+itemComparable.item.getNode()+"***, sur size="+set.usedResults.size()); 
      if (!set.usedResults.contains(itemComparable)); { 
       System.out.println("*** node "+itemComparable.item.getNode()+" not in usedResults"); 
      } 
      set.usedResults.add(itemComparable); 
     } 
    } 

    public static void main(String [] args) 
    { 
     Collection<ArbitraryItem> items = new ArrayList<>(); 
     for (int i = 0; i < 3; i++) { 
      items.add(new ArbitraryItem(""+i)); 
     } 

     Comparator<ArbitraryItemComparable> comparator = new Comparator<ArbitraryItemComparable>() { 
      @Override 
      public int compare(ArbitraryItemComparable o1, ArbitraryItemComparable o2) { 
       // this is where the magic needs to happen!! 
       System.out.println("calling compare: o1 node="+o1.item.getNode()+" "+o1.item.getNode().hashCode()+" o2 node="+o2.item.getNode()+" "+o2.item.getNode().hashCode()); 
       return o1.item.getNode().hashCode() - o2.item.getNode().hashCode(); 
      } 
      @Override 
      public boolean equals(Object o) { 
       System.out.println("why is this called?"); 
       return false; 
      } 
     }; 
     ResultSet set = new ResultSet("3", comparator); 
     idToArbitraryItems.put("q", set); 
     doRSM(items, set, 1000, false, "q"); 
     doRSM(items, set, 1000, false, "q"); 
    } 
} 

Однако журнал показывает это:

*** looking at node 0***, sur size=0 
*** node 0 not in usedResults 
calling compare: o1 node=0 48 o2 node=0 48 
    comparison val=0 
*** looking at node 1***, sur size=1 
calling compare: o1 node=1 49 o2 node=0 48 
    comparison val=1 
*** node 1 not in usedResults 
calling compare: o1 node=1 49 o2 node=0 48 
    comparison val=1 
*** looking at node 2***, sur size=2 
calling compare: o1 node=2 50 o2 node=0 48 
    comparison val=2 
calling compare: o1 node=2 50 o2 node=1 49 
    comparison val=1 
*** node 2 not in usedResults 
calling compare: o1 node=2 50 o2 node=0 48 
    comparison val=2 
calling compare: o1 node=2 50 o2 node=1 49 
    comparison val=1 
*** looking at node 0***, sur size=3 
calling compare: o1 node=0 48 o2 node=1 49 
    comparison val=-1 
calling compare: o1 node=0 48 o2 node=0 48 
    comparison val=0 
*** node 0 not in usedResults 
calling compare: o1 node=0 48 o2 node=1 49 
    comparison val=-1 
calling compare: o1 node=0 48 o2 node=0 48 
    comparison val=0 
*** looking at node 1***, sur size=3 
calling compare: o1 node=1 49 o2 node=1 49 
    comparison val=0 
*** node 1 not in usedResults 
calling compare: o1 node=1 49 o2 node=1 49 
    comparison val=0 
*** looking at node 2***, sur size=3 
calling compare: o1 node=2 50 o2 node=1 49 
    comparison val=1 
calling compare: o1 node=2 50 o2 node=2 50 
    comparison val=0 
*** node 2 not in usedResults 
calling compare: o1 node=2 50 o2 node=1 49 
    comparison val=1 
calling compare: o1 node=2 50 o2 node=2 50 
    comparison val=0 

Линии обижая начать здесь:

*** looking at node 0***, sur size=3 
calling compare: o1 node=0 48 o2 node=1 49 
    comparison val=-1 
calling compare: o1 node=0 48 o2 node=0 48 
    comparison val=0 
*** node 0 not in usedResults 

Значит, что значение сравнения равно 0 (это означает, что они равны), и все же добавочный код все еще вызывается, что означает, что в списке не указано t hat содержит значение. Зачем? Я думал, что возвращение compareTo из 0 означает равенство? Кроме того, почему equals никогда не называется? В TreeSet документации состояния для contains:

Возвращает истину, если этот набор содержит указанный элемент. Более формально возвращает true тогда и только тогда, когда этот набор содержит элемент e такой, что (o == null? E == null: o.equals (e)).

Что привело бы меня к мысли, что будет называться ArbitraryItemComparable.equals, но это не так? Любые идеи о том, как вернуть функцию usedResults.contains, чтобы вернуть true?

+2

Вы опубликовали много кода с большим количеством результатов, используя несколько разных коллекций, что затрудняет определение того, что происходит * и *, о чем вы спрашиваете. Не могли бы вы привести пример к более простой? –

+1

Не забывайте учитывать переполнение условия 'o1.hashCode() - o2.hashCode()'. Это создает странные ошибки – Ferrybig

+0

Похоже, что нет переполнения в том, что он говорит, что вычитание возвращает 0. – mikesol

ответ

3

У вас есть это:

... 
if (!set.usedResults.contains(itemComparable)); { // NOTE THE SEMICOLON!!!! 

Это в основном означает «игнорировать это условие и безоговорочно выполнить следующий блок».

+1

Инструменты статического анализа будут предупреждать об этих проблемах, я использую NetBeans, а среда ID подчеркивает что-либо «подозрительное». Но вам не следует игнорировать подчеркивания и на самом деле проверить, что происходит – gpeche

+0

Ух, затмение даже не подчеркивало это ... – mikesol

Смежные вопросы