Java 8复杂的自定义收集器

Ido*_*ash 6 java java-8 java-stream

我有一个对象流,我想通过以下方式收集.

假设我们正在处理论坛帖子:

class Post {
    private Date time;
    private Data data
}
Run Code Online (Sandbox Code Playgroud)

我想创建一个列表,按时间段对帖子进行分组.如果X分钟没有帖子,请创建新组.

class PostsGroup{
    List<Post> posts = new ArrayList<> ();
}
Run Code Online (Sandbox Code Playgroud)

我希望得到一个List<PostGroups>按时间间隔分组的帖子.

例如:间隔10分钟.

帖子:

[{time:x, data:{}}, {time:x + 3, data:{}} , {time:x+ 12, data:{}, {time:x + 45, data:{}}}]
Run Code Online (Sandbox Code Playgroud)

我想获得一个帖子组列表:

[
 {posts : [{time:x, data:{}}, {time:x + 3, data:{}}, {time:x+ 12, data:{}]]},
{posts : [{time:x+ 45, data:{}]}
]
Run Code Online (Sandbox Code Playgroud)
  • 注意第一组持续到X + 22.然后在X + 45收到一个新帖子.

这可能吗?

Old*_*eon 0

您需要保留流条目之间的状态并自己编写一个分组分类器。像这样的事情将是一个好的开始。

class Post {

    private final long time;
    private final String data;

    public Post(long time, String data) {
        this.time = time;
        this.data = data;
    }

    @Override
    public String toString() {
        return "Post{" + "time=" + time + ", data=" + data + '}';
    }

}

public void test() {
    System.out.println("Hello");
    long t = 0;
    List<Post> posts = Arrays.asList(
            new Post(t, "One"),
            new Post(t + 1000, "Two"),
            new Post(t + 10000, "Three")
    );
    // Group every 5 seconds.
    Map<Long, List<Post>> gouped = posts
            .stream()
            .collect(Collectors.groupingBy(new ClassifyByTimeBetween(5000)));
    gouped.entrySet().stream().forEach((e) -> {
        System.out.println(e.getKey() + " -> " + e.getValue());
    });

}

class ClassifyByTimeBetween implements Function<Post, Long> {

    final long delay;
    long currentGroupBy = -1;
    long lastDateSeen = -1;

    public ClassifyByTimeBetween(long delay) {
        this.delay = delay;
    }

    @Override
    public Long apply(Post p) {
        if (lastDateSeen >= 0) {
            if (p.time > lastDateSeen + delay) {
                // Grab this one.
                currentGroupBy = p.time;
            }
        } else {
            // First time - start there.
            currentGroupBy = p.time;
        }
        lastDateSeen = p.time;
        return currentGroupBy;
    }

}
Run Code Online (Sandbox Code Playgroud)