Replace for loop with lambda

Viewed 261

i have a following code:

@Override
public String parsePrice(Document document) {
    Elements metaElements = document.getElementsByTag("meta");
    for (Element tag : metaElements) {
        String content = tag.attr("content");
        String item = tag.attr("itemprop");

        if ("price".equals(item)) {
            return content.equals("0") ? "Free" : content;
        }
    }
    return "Information not available";
}

It will return a price like "7,49$". I want to replace this code with java 8 features. I'm newbie with streams, but tried:

metaElements.stream().filter(tag -> "price".equals(tag.attr("itemprop")))
                .findFirst().orElse(null);

But it returns <meta itemprop="price" content="7,49$">

I can't filter like this (missing return statement):

metaElements.stream().filter(tag -> {
            String content = tag.attr("content");
            String item = tag.attr("itemprop");

            if ("price".equals(item)) {
                return content.equals("0") ? "Free" : content;
            }
        }).findFirst().orElse(null);

How to fix it?

2 Answers

Your attempt here was close:

metaElements.stream()
            .filter(tag -> "price".equals(tag.attr("itemprop")))
            .findFirst()
            .orElse(null);

you just needed to map + orElse after findFirst e.g.

return metaElements.stream()
            .filter(tag -> "price".equals(tag.attr("itemprop")))
            .findFirst()
            .map(tag -> tag.attr("content").equals("0") ? 
                         "Free" : tag.attr("content"))
            .orElse("Information not available");

You are close!

metaElements.stream()
        .filter(tag -> "price".equals(tag.attr("itemprop")))
        .findFirst()
        .map(tag -> tag.attr("content"))
        .map(price -> "0".equals(price) ? "Free" : price)
        .orElse("Information not available")

I prefer to keep the lambda's short and chain multiple Stream operators, so the overall code looks more readable (imo).

  1. Look at all the tags and find me those named "price"
  2. I'm only interested in the first occurrence (or know that there will be one at most)
  3. Now extract the actual price
  4. Transform the price to the desired format
  5. Or if any of the previous stages fail... return N/A
Related