Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 complex custom collector

I have a stream of objects which I would like to collect the following way.

Let's say we are handling forum posts:

class Post {
    private Date time;
    private Data data
}

I want to create a list which groups posts by a period. If there were no posts for X minutes, create a new group.

class PostsGroup{
    List<Post> posts = new ArrayList<> ();
}

I want to get a List<PostGroups> containing the posts grouped by the interval.

Example: interval of 10 minutes.

Posts:

[{time:x, data:{}}, {time:x + 3, data:{}} , {time:x + 12, data:{}, {time:x + 45, data:{}}}]

I want to get a list of posts group:

[
 {posts : [{time:x, data:{}}, {time:x + 3, data:{}}, {time:x + 12, data:{}]]},
{posts : [{time:x + 45, data:{}]}
]
  • notice that the first group lasted till X + 22. Then a new post was received at X + 45.

Is this possible?

like image 761
Ido Barash Avatar asked Dec 22 '15 13:12

Ido Barash


People also ask

What does .collect do in Java?

collect() is one of the Java 8's Stream API's terminal methods. It allows us to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.

What is groupingBy in Java?

The groupingBy() method of Collectors class in Java are used for grouping objects by some property and storing results in a Map instance.


1 Answers

This problem could be easily solved using the groupRuns method of my StreamEx library:

long MAX_INTERVAL = TimeUnit.MINUTES.toMillis(10);
StreamEx.of(posts)
        .groupRuns((p1, p2) -> p2.time.getTime() - p1.time.getTime() <= MAX_INTERVAL)
        .map(PostsGroup::new)
        .toList();

I assume that you have a constructor

class PostsGroup {
    private List<Post> posts;

    public PostsGroup(List<Post> posts) {
        this.posts = posts;
    }
}

The StreamEx.groupRuns method takes a BiPredicate which is applied to two adjacent input elements and returns true if they must be grouped together. This method creates the stream of lists where each list represents the group. This method is lazy and works fine with parallel streams.

like image 97
Tagir Valeev Avatar answered Sep 28 '22 16:09

Tagir Valeev