2016-09-08 2 views
1

Я написал фрагмент кода, чтобы узнать больше о функции java collection для Comparator. У меня есть два набора, каждый из которых имеет по 3 элемента. и я хочу сравнить. Я отправляю свой код ниже и вывод переменной счетчика. Может ли кто-нибудь объяснить, почему переменная i дает этот странный результат? Я не мог понять поток.Странный вывод переменной счетчика в компараторе java

public class TestProductBundle { 
public static void main(String args[]) { 

    TestProductBundle productBundle = new TestProductBundle(); 

    Set<ClassA> hashSetA = new HashSet<ClassA>() { 
     { 
      add(new ClassA("name", 1, "desc")); 
      add(new ClassA("name", 2, "desc")); 
      add(new ClassA("name", 3, "desc")); 
     } 
    }; 

    Set<ClassA> hashSetB = new HashSet<ClassA>() { 
     { 
      add(new ClassA("name1", 2, "desc1"));  //"name" & "desc" are different than previous 
      add(new ClassA("name2", 1, "desc2")); 
      add(new ClassA("name3", 3, "desc3")); 
     } 
    }; 

    if (productBundle.compareCollection(hashSetA, hashSetB)) { 
     System.out.println("Equal set of tree"); 
    } else { 
     System.out.println("Unequal set of tree"); 
    } 
} 

@SuppressWarnings("serial") 
public boolean compareCollection(Set<ClassA> collection1, Set<ClassA> collection2) { 

    TreeSet<ClassA> treeSetA = new TreeSet<ClassA>(new CompareID()) { 
     { 
      addAll(collection1); 
     } 
    }; 

    TreeSet<ClassA> treeSetB = new TreeSet<ClassA>(new CompareID()) { 
     { 
      addAll(collection2); 
     } 
    }; 

    if (treeSetA.containsAll(treeSetB) && treeSetB.containsAll(treeSetA)) 
     return true; 
    else 
     return false; 
    } 
} 

код для ClassA и класса, который реализует компаратор.

class ClassA { 
String name; 
int id; 
String desc; 

public ClassA(String name, int id, String desc) { 
    this.name = name; 
    this.id = id; 
    this.desc = desc; 
} 

int getId() { 
    return id; 
    } 
} 

&

class CompareID implements Comparator<ClassA> { 
    int i = 0; 

    @Override 
    public int compare(ClassA o1, ClassA o2) { 
     System.out.println(i++);     // Counter variable 
     if (o1.getId() > o2.getId()) 
      return 1; 
     else if (o1.getId() < o2.getId()) 
      return -1; 
     else 
      return 0; 

    } 
} 

выход (кросс проверяется в отладчик также)

0 
1 
2 
3 
0 // why started from 0 again ? 
1  
2 
3 
4 
5 
6 
7 
8 
4 // What the hell !!! 
5 
6 
7 
8 
Equal set of tree // is that correct output ? 
+1

, что вы ожидали бы там, чтобы сделать это не выглядеть странно? – SomeJavaGuy

+0

У меня нет подсказки, почему он начинается с 4 после 8, также 0 после 3. – user3042916

+0

Опять же, что вы ожидаете увидеть? Как то, что вы видите, отличается от того, что вы ожидаете увидеть? Хорошие детали. – jwpfox

ответ

3

Я не уверен, что вы обнаружили странное. У вас есть два экземпляра TreeSet, каждый из которых имеет свой собственный экземпляр CompareID, служащий как Comparator, и каждый экземпляр CompareID хранит его собственный счетчик.

Поэтому не удивительно видеть, что каждое значение счетчика (0,1,2 и т. Д.) Появляется дважды. Что касается порядка появления значений счетчика, то это зависит от внутренней реализации TreeSet.

Что касается

Ровный набор дерева // это правильно выход?

Да, оба набора содержат одинаковые элементы. Приказ не имеет значения. Для уточнения - методы contains и containsAll из TreeSet рассмотрят элемент x, которые должны содержаться в TreeSet, если compare(x,y)==0 для некоторого элемента y из TreeSet, где comparecompare является методом поставляемого Comparator. Поэтому в вашем примере только свойство id определяет, являются ли два элемента равными.

Следующий сценарий объясняет выход:

0 // compare method of 1st CompareID object executed 
1 // compare method of 1st CompareID object executed 
2 // compare method of 1st CompareID object executed 
3 // compare method of 1st CompareID object executed 
0 // compare method of 2nd CompareID object executed 
1 // compare method of 2nd CompareID object executed  
2 // compare method of 2nd CompareID object executed 
3 // compare method of 2nd CompareID object executed 
4 // compare method of 1st CompareID object executed 
5 // compare method of 1st CompareID object executed 
6 // compare method of 1st CompareID object executed 
7 // compare method of 1st CompareID object executed 
8 // compare method of 1st CompareID object executed 
4 // compare method of 2nd CompareID object executed 
5 // compare method of 2nd CompareID object executed 
6 // compare method of 2nd CompareID object executed 
7 // compare method of 2nd CompareID object executed 
8 // compare method of 2nd CompareID object executed 

EDIT: Во-первых вы добавление элементов к первому TreeSet (отсюда compare первого Comparator вызывается несколько раз подряд), то вы добавления элементов ко второму TreeSet (отсюда compare второго Comparator вызывается несколько раз подряд), то вы звоните treeSetA.containsAll(treeSetB)compare, который вызывает первого Comparator, чтобы назвать несколько раз подряд, и, наконец, вы называете treeSetB.containsAll(treeSetA), который вызывает compare второго Comparator, который будет вызываться несколько раз подряд.

+0

Как насчет «4» после «8»? – user3042916

+0

«Да, оба набора содержат одни и те же элементы. Порядок не имеет значения». ----> Элементы разные, посмотрите на имя и описание из второго набора, пожалуйста. – user3042916

+1

@ user3042916 Они являются теми же элементами, что и для компаратора, поскольку это касается только свойства id. – Eran

1

Здесь переменная i будет инициализирована для двух объектов-компараторов, ваша инициализация i = 0, в соответствии с вашей точкой здесь будет использоваться метод сравнения для обоих наборов, которые не обязательно должны быть последовательно, так что происходит, вы ожидаете последовательности но на самом деле его нет

0// for set1(collection1) 
1 
2 
3 // remember this value for set 1 
0 // for set2(collection2) 
1  
2 
3 
4 
5 
6 
7 
8 
4 for set1(collection1 which was 3 and now increment to 1) 
5 
6 
7 
8 
1

Добавление к ответу @Erans.

Изменить код ниже и вы увидите, который comperator делает вывод, когда

class CompareID implements Comparator<ClassA> { 
    int i = 0; 
    String a; 
    public CompareID(String input) { 
     a = input; 
    } 
    @Override 
    public int compare(ClassA o1, ClassA o2) { 
     // Output comperator "id" 
     System.out.println(a+ " " + i++); // Counter variable 
     if (o1.getId() > o2.getId()) 
      return 1; 
     else if (o1.getId() < o2.getId()) 
      return -1; 
     else 
      return 0; 

    } 
} 

... 

    TreeSet<ClassA> treeSetA = new TreeSet<ClassA>(new CompareID("A")) { 
     { 
      addAll(collection1); 
     } 
    }; 

    TreeSet<ClassA> treeSetB = new TreeSet<ClassA>(new CompareID("B")) { 
     { 
      addAll(collection2); 
     } 
    }; 

Выход изменится к следующему. Комментарии включают то, что было произвести вывод:

// This is addALL treeSetA 
A 0 
A 1 
A 2 
A 3 
// this is addAll treeSetB 
B 0 
B 1 
B 2 
B 3 
// this is treeSetA.containsAll(treeSetB) 
A 4 
A 5 
A 6 
A 7 
A 8 
// this is treeSetB.containsAll(treeSetA) 
B 4 
B 5 
B 6 
B 7 
B 8 

поясню как comperators только выходные

0-8 
0-8 
+0

Мне любопытно, вы можете объяснить мне, почему это не синхронизировано? – user3042916

+0

@ user3042916 Я действительно редактировал его, пропустил что-то там, комментарий на выходе должен помочь сейчас;) – SomeJavaGuy

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