33

I've got Google Guava inside Stream:

this.map.entrySet().stream()
.filter(entity -> !Strings.isNullOrEmpty(entity.getValue()))
.map(obj -> String.format("%s=%s", obj.getKey(), obj.getValue()))
.collect(Collectors.joining(","))

As you see there is a statement !String.isNullOrEmpty(entity) inside the filter function.

I don't want to use Guava anymore in the project, so I just want to replace it simply by:

string == null || string.length() == 0;

How can I do it more elegant?

1ac0
  • 2,875
  • 3
  • 33
  • 47
ServerSideCat
  • 1,992
  • 3
  • 18
  • 24

6 Answers6

34

In java 11 there is a new method Predicate::not.

So you can filter out empty string :

list.stream()
  .filter(Objects::nonNull)
  .filter(Predicate.not(String::isEmpty))
lczapski
  • 4,026
  • 3
  • 16
  • 32
29

You can write your own predicate:

final Predicate<Map.Entry<?, String>> valueNotNullOrEmpty
    = e -> e.getValue() != null && !e.getValue().isEmpty();

Then just use valueNotNullOrEmpty as your filter argument.

fge
  • 119,121
  • 33
  • 254
  • 329
  • Predicate's in Java 8 looks like an elegant solution. However, i'm not able to use your example in my code since we are operating Strings instead of work with Map.Entry,?>. Could you optimize it? – ServerSideCat Jul 13 '15 at 11:09
  • 3
    What about you showed the real code in your question, then? As I said, the current code extract just won't compile – fge Jul 13 '15 at 11:10
  • 1
    I don't even need to try; again: Strings.isNullOrEmpty() won't work on a Map.Entry, ?>. It is either this or your `map` is not a `Map, ?>`. Please paste the real code. – fge Jul 13 '15 at 11:20
  • Anyhow using Predicate for me is the most elegant variant – ServerSideCat Jul 13 '15 at 11:33
  • 3
    Image won't display for me; and you can OMG all you want, this is a fact: the code you posted in the question will not compile. – fge Jul 13 '15 at 11:34
  • @Holger don't get it. Guys, this is just the thing i see in working project with any compile errors. Could you just believe this fact. – ServerSideCat Jul 13 '15 at 11:36
  • 3
    @ServerSideCat: no, we can’t. We are *programmers*. Our work is based on facts, like that a `Map.Entry` is not a `String`. We can’t accept that code that claims otherwise shall work because you say “I see it working”. As it is not a matter of looking at it but *understanding* what’s going on. If you understood the point, you did everything to find out, where’s the mismatch. When obviously wrong code appears to work, it should make you nervous, especially when it is production code. – Holger Jul 13 '15 at 11:40
  • 1
    @ServerSideCat this is just not believable; either this or this is not Guava's `Strings#isNullOrEmpty` – fge Jul 13 '15 at 11:40
  • @Holger Hey, programmer. Don't you see that Compiler allows to do that just because in my map() method i'm operating with String. Could you just paste this code into your IDE and open your eyes, programmer. – ServerSideCat Jul 13 '15 at 11:43
  • 4
    You are calling `filter(…)` on a `entrySet().stream()`, thus it expects a `Predicate>`. Point. Obviously, copying the code of your question can’t compile anyway since not even the definition of `map` is there. If you compared the code you have posted on that image hoster with the code you have posted in your question, you noticed the small `getValue()` call that is missing here, which makes a huge difference. You just failed to do a proper copy and paste. – Holger Jul 13 '15 at 11:47
  • 4
    @ServerSideCat, your screenshot has `isNullOrEmpty(entity.getValue())` while in your question it's just `isNullOrEmpty(entity)`. – Tagir Valeev Jul 13 '15 at 11:52
  • @TagirValeev yes, this is exactly the problem – ServerSideCat Jul 13 '15 at 11:54
22

If you prefer to use commons-lang3, StringUtils has

  • isEmpty()
  • isNotEmpty()
  • isBlank()
  • isNotBlank()

These methods can be used in filters as method references:

this.stringList.stream().filter(StringUtils::isNotBlank);

or as lambdas:

this.stringList.stream().filter(s -> StringUtils.isNotBlank(s));
Laurel
  • 5,965
  • 14
  • 31
  • 57
rvertigo
  • 275
  • 2
  • 6
  • 1
    I think the isBlank() isNotBlank() methods are very useful, but just so others are aware, they are different than isNullOrEmpty() in that they also check for other whitespace characters such as tabs, carriage returns, etc. This is defined by the isWhiteSpace() function in Java: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Character.html#isWhitespace(char) – Josh Maag Sep 11 '20 at 14:23
9

You can create your own Strings class with your own predicate:

public class Strings {
  public static boolean isNotNullOrEmpty (String str) {
    return str != null && !str.isEmpty();
  }
}

Then in your code:

.filter(Strings::isNotNullOrEmpty)

But as @fge mentionned, you can't use that on a Map.Entry<?,?>...

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
3

You can break down the filter into two steps:

this.map.entrySet().stream()
    .filter(entity -> entity.getValue() != null)
    .filter(entity -> !entity.getValue().isEmpty())
    .map(obj -> String.format("%s=%s", obj.getKey(), obj.getValue()))
    .collect(Collectors.joining(","))

On a side note, most Map.Entry.toString() implementations do exactly what you're doing in map(), so you could theoretically just do map(Map.Entry::toString). But I wouldn't rely on that unless you're producing a toString() or something that doesn't require documented or deterministic behavior.

Also, I know you want to abandon Guava, but here's a solution that might make you reconsider:

Joiner.on(',').withKeyValueSeparator("=")
      .join(Maps.filterValues(map, Predicates.not(Strings::isNullOrEmpty)));
shmosel
  • 49,289
  • 6
  • 73
  • 138
2

It works for me: list.stream().filter(el-> el != null && !el.toString().trim().isEmpty()).collect(Collectors.toList());

Taras Melnyk
  • 3,057
  • 3
  • 38
  • 34