user9132502
user9132502

Reputation:

How to compare every objects in iterator with compareTo

I have a model class Person which implements the Comparable interface and a compareTo(Personne o) method which returns the proper int depending on the person's age.

Usecase: I want to check if all the persons inside the collection have the same age with an iterator

What I have so far:

while (collectionOfPerson.hasNext()) {
    Person pers = collectionOfPerson.next();
    if (pers.comparTo(collectionOfPerson.next()) == 0) {

    }
}

Upvotes: 4

Views: 3045

Answers (3)

Zabuzard
Zabuzard

Reputation: 25903

It is enough to grab only the first person and compare this to every other person, as you are testing if all have the same age.

Also, your comparison isn't correct, you have:

pers.comparTo(collectionOfPerson.next()) == 0

So you are trying to compare the current person to the next. But you have not tested if there is another person yet. So if you reached the end you will try to access a non existing person, yielding an error. You could easily fix that by comparing to the person of the last iteration. But, as said, you don't need that and could just compare to the first person every time.

Also, you should test for mismatch, not for matching ages.

Person first = collectionOfPerson.next();
while (collectionOfPerson.hasNext()) {
    Person other = collectionOfPerson.next();
    if (first.comparTo(other) != 0) {
        // Found mismatch, abort
        return false;
    }
}
// Didn't found mismatch
return true;

Or a Stream example that does not use Iterator:

Person first = persons.iterator().next();

boolean allSameAge = persons.stream()
    .allMatch(p -> p.compareTo(first) == 0);

An alternative using the enhanced for loop (for-each):

Person first = persons.iterator().next();
for (Person other : persons) {
    if (other.compareTo(first) != 0) {
        return false;
    }
}
return true;

The following example filters all persons with the same age, only different ages remain. By that you can also easily collect the persons with other ages:

Person first = persons.iterator().next();
List<Person> otherAgePersons = persons.stream()
    .filter(p -> p.compareTo(first) != 0)
    .collect(Collectors.toList());

Upvotes: 3

Pau Trepat
Pau Trepat

Reputation: 717

I advocate for one solution using only streams.

Optional<Person> anyPerson = persons.stream().findAny();

boolean allSameAge = persons.stream()
    .allMatch(p -> p.compareTo(anyPerson.get()) == 0);

I have to say that's not a semantic solution but it doesn't requires more work implementing new functions.

Following DDD to get a more semantic code you can change compareTo function for another which could be placed in Person class and have this contract:

public boolean hasSameAge(Person p);

Upvotes: 2

Jacob G.
Jacob G.

Reputation: 29710

Usecase: I want to check if all the persons inside the collection have the same age with an iterator

You can take advantage of streams along with an Iterator if you'd like, assuming you a getAge method within Person and collectionOfPerson is not empty:

if (!collectionOfPerson.hasNext()) {
    return;
}

int age = collectionOfPerson.next().getAge();

collectionOfPerson.stream()
                  .mapToInt(Person::getAge)
                  .allMatch(i -> i == age);

If you're dead-set on solely using an Iterator<Person>, then you were close! You can keep track of a boolean and break out of the loop if any of the elements in the collection do not match the age of the first element:

if (!collectionOfPerson.hasNext()) {
    return;
}

int age = collectionOfPerson.next().getAge();

boolean allMatch = true;

while (collectionOfPerson.hasNext()) {
    if (collectionOfPerson.next().getAge() != age) {
        allMatch = false;
        break;
    }
}

if (allMatch) {
    // All of the ages are the same!
}

Upvotes: 3

Related Questions