Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Java 8 streams and the Drastic Impact on Loops

0.00/5 (No votes)
30 Jun 2015CPOL2 min read 5.6K  
Java 8 streams and the drastic impact with loops

Java 8 is a game changer. There is no question about that. Java 7 barely made a splash, but Java 8 is like Java 5 which introduced generics, annotations, and so on. I may be a little late to the party on Java 8 but in corporate America, things become relevant a little slower. One of the ways Java 8 has changed things is with streams and how it has changed the way we can do loops.

Here is a little code to show you how things can be different with streams. I will go into more detail but this is just to start the discussion with code.

Java
 public void doStuff() throws Exception {
 List<BlogPost > posts = new ArrayList<>();
 BlogPost post1 = new BlogPost();
 post1.setTile("num1");
 post1.setTags(Arrays.asList("A", "B", "C"));
 posts.add(post1);
 BlogPost post2 = new BlogPost();
 post2.setTile("num1");
 post2.setTags(Arrays.asList("C", "D", "E"));
 posts.add(post2);


 BlogPost result1 = getRelatedPostLoop(posts, "D");
 Optional<BlogPost > result2 =
                       getRelatedPostStream(posts, "D");

 if (result1 != result2.get()) {
  throw new Exception("error");
 }

 BlogPost result3 = getRelatedPostLoop(posts, "F");
 Optional<Blogpost> result4 =
                       getRelatedPostStream(posts, "F");

 if (result3 != null || result4.isPresent()) {
  throw new Exception("error");
 }
}

//Java 7 way
private BlogPost getRelatedPostLoop(List<BlogPost> posts,
               String tag) {
    for (BlogPost post : posts) {
        if (post.getTags().contains(tag)) {
            return post;
        }
    }
    return null;
}

//Java 8 way
private Optional<BlogPost> getRelatedPostStream(
               List<BlogPost > posts, String tag) {

 return posts.stream()
         .filter(post -> post.getTags().contains(tag))
         .findFirst();
}

private class BlogPost {

 private String tile;
 private StringBuffer body;
 private List<String> tags;
 public String getTile() {
  return tile;
 }
 public void setTile(String tile) {
  this.tile = tile;
 }
 public StringBuffer getBody() {
  return body;
 }
 public void setBody(StringBuffer body) {
  this.body = body;
 }
 public List<string> getTags() {
  return tags;
 }
 public void setTags(List<String> tags) {
  this.tags = tags;
 }
}

Pretty cool, right? Single pass loops can be made a lot simpler with the use of streams. The list is being used as a stream which does the same as a for loop. The filter operation does exactly what you would expect; it filters each element in the list by a condition passed in through the argument. Lastly, findFirst pretty clearly from its name again returns the first element from the stream or null if the stream is empty.

Other hidden gems in that code thanks to Java 8:

  • Java
    List<BlogPost > posts = new ArrayList<>();

    This is a simple thing but reduces frustration. How many times have you been frustrated because you had to cut and paste the same generic on both sides of an assignment? You are writing the assignment inline why does the compiler really need you to specify it twice! Well, now you don't have to.

  • Java
    Optional<BlogPost>

    Optional is a new class which helps make it clear that a null object response can be returned and adds in some helper methods to work with that possibly null value cleanly.

More examples of how streams can be done to make the code a little cleaner:

  • Here is a simple way to return the filtered matches as a collection. There is no need to create the in scope list variable to be used in the response.
    Java
    private List<BlogPost> getAllRelatedPosts(
                   List<BlogPost > posts, String tag) {
     return posts.stream()
             .filter(post -> post.getTags().contains(tag))
             .collect(Collectors.toList());
    }
    
  • Also, here is a simple way to return the filtered matches but only the distinct matches. Small change but showing the power here.
    Java
    private Set<BlogPost> getAllRelatedPosts(
                   List<BlogPost> posts, String tag) {
     return posts.stream()
             .filter(post -> post.getTags().contains(tag))
             .collect(Collectors.toSet());
    }
    
  • Even performing operations to say get a sum total based upon a loop variable method is easy:
    Java
    private int getTagCount(List<BlogPost> posts) {
     return posts.stream()
       .mapToInt(
                                        post ->
                                           post.getTags().size())
       .sum();
    }
    
  • The magic continues on and on but those are things you really should explore on your own

Potentially helpful link:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)