Thursday 14 December 2023

Streams and Filters

A simple little thing.

I like to use streams and filters, and I was wondering what's the best way to go about some things.

For example: I wish to search for a person in a list of Persons.

  @Test
  public void testSimple() {
    Person personToFind = new Person(null, "Mr.", "Bear", "Netherlands");
    Person otherPersonToFind = new Person(null, "Linda", "Lovelace", "England");
    assertThat(Persons.get().stream()
        .filter(person -> Objects.equals(personToFind.name(), person.name()) &&
            Objects.equals(personToFind.surname(), person.surname()) &&
            Objects.equals(personToFind.country(), person.country()))
        .findFirst()).isPresent();

    assertThat(Persons.get().stream()
        .filter(person -> Objects.equals(otherPersonToFind.name(), person.name()) &&
            Objects.equals(otherPersonToFind.surname(), person.surname()) &&
            Objects.equals(otherPersonToFind.country(), person.country()))
        .findFirst()).isEmpty();
  }

This works, but the single filter with all the && in it seems a bit unreadable.

Of course, I could replace the x&&y&&z by three filters, as it boils down tot the same thing.

  @Test
  public void testSimple2() {
    Person personToFind = new Person(null, "Mr.", "Bear", "Netherlands");
    Person otherPersonToFind = new Person(null, "Linda", "Lovelace", "England");
    assertThat(Persons.get().stream()
        .filter(person -> Objects.equals(personToFind.name(), person.name()))
        .filter(person -> Objects.equals(personToFind.surname(), person.surname()))
        .filter(person -> Objects.equals(personToFind.country(), person.country()))
        .findFirst()).isPresent();

    assertThat(Persons.get().stream()
        .filter(person -> Objects.equals(otherPersonToFind.name(), person.name()))
        .filter(person -> Objects.equals(otherPersonToFind.surname(), person.surname()))
        .filter(person -> Objects.equals(otherPersonToFind.country(), person.country()))
        .findFirst()).isEmpty();
  }

But my colleague always likes to use specific methods for lambdas, even if they're only a little complex. It just reads easier.

private boolean compare(Person person, Person otherPerson) {
    return Objects.equals(otherPerson.name(), person.name()) &&
        Objects.equals(otherPerson.surname(), person.surname()) &&
        Objects.equals(otherPerson.country(), person.country());
  }

  @Test
  public void testSimple3() {
    Person personToFind = new Person(null, "Mr.", "Bear", "Netherlands");
    Person otherPersonToFind = new Person(null, "Linda", "Lovelace", "England");
    assertThat(Persons.get().stream()
        .filter(person -> compare(person, personToFind))
        .findFirst()).isPresent();

    assertThat(Persons.get().stream()
        .filter(person -> compare(person, otherPersonToFind))
        .findFirst()).isEmpty();
  }

My personal preference is the last one.

No comments:

Post a Comment