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

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 и класса, реализующего Comparator.

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
user3042916 8 Сен 2016 в 11:45

3 ответа

Лучший ответ

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

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

Что касается

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

Да, оба набора содержат одинаковые элементы. Порядок не имеет значения. Чтобы уточнить - методы contains и containsAll из TreeSet считают, что элемент x содержится в TreeSet, если compare(x,y)==0 для некоторого элемента { {X6}} из TreeSet, где compare - метод compare предоставленного 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

РЕДАКТИРОВАТЬ: сначала вы добавляете элементы к первому TreeSet (следовательно, compare первого Comparator вызывается несколько раз подряд), затем вы добавляете элементы ко второму {{X3 }} (следовательно, compare второго Comparator вызывается несколько раз подряд), затем вы вызываете treeSetA.containsAll(treeSetB), что вызывает compare первого Comparator вызывается несколько раз подряд, и, наконец, вы вызываете treeSetB.containsAll(treeSetA), что вызывает вызов compare второго Comparator несколько раз подряд.

3
Eran 8 Сен 2016 в 09:09

Здесь переменная 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
Jekin Kalariya 8 Сен 2016 в 08:57

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

Измените код на следующий, и вы увидите, какой компилятор выводит, когда

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

В основном оба конкурента просто выводят

0-8
0-8
1
SomeJavaGuy 8 Сен 2016 в 09:10