How to know if the list contains so many elements that meet and do not meet a condition, using stream?

Asked

Viewed 64 times

5

I have a list of columns, I need to know if this list contains both columns that are keys and columns that are not keys.

I guarantee the existence of at least one column on the list

My class of column:

public class Coluna {
  public boolean chave;
  public boolean isChave() { return chave; }
}

My check is like this at the moment:

List<Coluna> minhasColunas = ...;
Predicate<Coluna> ehChave = Coluna::isChave;
boolean possuiColunasMistas =
    minhasColunas.stream().anyMatch(ehChave) &&
    minhasColunas.stream().anyMatch(ehChave.negate());

Is there any more idiomatic way to do this check? I found it very strange to go through two streams to obtain the result.

On a more imperative check, I would do the following:

List<Coluna> minhasColunas = ...;
boolean achouChave = false;
boolean achouNaoChave = false;
for (Coluna c: minhasColunas) {
  if (c.chave) {
    achouChave = true;
    if (achouNaoChave) {
      break;
    }
  } else {
    achouNaoChave = true;
    if (achouChave) {
      break;
    }
  }
}

boolean possuiColunasMistas = achouChave && achouNaoChave;

After the creation of the question, and conversation with the @Anderson Carlos Woss, I ended up creating some test scenarios for that question. They are available here: https://gitlab.com/snippets/1724680

So if you want to validate your own response, implement the method boolean possuiColunasMistas(List<Coluna> colunas) and then just run with Junit the test cases.

  • It is necessary to use stream or a reply iterating a for is valid ?

  • @Viníciusferreira my ultimate goal is elegance. In this question, it was really how to use stream, I sensed I had something wrong. So, elegant answers are appreciated, even though the focus is not

1 answer

2


A slightly simpler logic would be to take the value of the first element of the list and just check if there is any other one in it. If the list is homogeneous, all values will be equal and therefore you will not find a different value.

I believe it would be close to:

boolean primeiraChave = lista.get(0).isChave();
boolean possuiColunasMistas = lista.stream().skip(1).anyMatch(it -> it.isChave() != primeiraChave)

Thus possuiColunasMistas will be true only for heterogeneous lists.

Note: use the skip(1) is optional, since comparing the first element with itself will not change the result; but it also makes no sense to check if it is different from itself.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.