Java 8复杂自定义收集器
我有一个对象流,我想收集以下方式 假设我们正在处理论坛帖子:Java 8复杂自定义收集器,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个对象流,我想收集以下方式 假设我们正在处理论坛帖子: class Post { private Date time; private Data data } 我想创建一个列表,按时段对帖子进行分组。如果X分钟内没有帖子,请创建新组 class PostsGroup{ List<Post> posts = new ArrayList<> (); } 我想获得一个组中的帖子列表: [ {posts : [{time:x, data:{}}
class Post {
private Date time;
private Data data
}
我想创建一个列表,按时段对帖子进行分组。如果X分钟内没有帖子,请创建新组
class PostsGroup{
List<Post> posts = new ArrayList<> ();
}
我想获得一个组中的帖子列表:
[
{posts : [{time:x, data:{}}, {time:x + 3, data:{}}, {time:x+ 12, data:{}]]},
{posts : [{time:x+ 45, data:{}]}
]
- 请注意,第一组持续到X+22。然后在X+45收到一个新的邮件
这可能吗?您需要保留流条目之间的状态,并为自己编写一个分组分类器。像这样的事情将是一个好的开始
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;
}
}
class Post{
私人最终很长时间;
私有最终字符串数据;
公共帖子(长时间,字符串数据){
这个时间=时间;
这个数据=数据;
}
@凌驾
公共字符串toString(){
返回“Post{“+”time=“+time+”,data=“+data+'}”;
}
}
公开无效测试(){
System.out.println(“你好”);
长t=0;
List posts=Arrays.asList(
新职位(t,“一”),
新员额(t+1000,“两个”),
新员额(t+10 000,“三个”)
);
//每5秒分组一次。
地图被挖出=柱子
.stream()
.collect(Collectors.groupingBy(新分类BYTimebetween(5000));
gouped.entrySet().stream().forEach((e)->{
System.out.println(e.getKey()+“->”+e.getValue());
});
}
类ClassifyByTimeBetween实现函数{
最终长延时;
长currentGroupBy=-1;
long lastDateSeen=-1;
公共分类ByTimeBetween(长延迟){
延迟=延迟;
}
@凌驾
公开长期申请(p职位){
如果(lastDateSeen>=0){
如果(p.time>lastDateSeen+延迟){
//抓住这个。
currentGroupBy=p.time;
}
}否则{
//第一次-从那里开始。
currentGroupBy=p.time;
}
lastDateSeen=p.time;
返回当前GroupBy;
}
}
使用my library的方法可以轻松解决此问题:
long MAX_INTERVAL=TimeUnit.MINUTES.toMillis(10);
第十条(员额)
.groupRuns((p1,p2)->p2.time.getTime()-p1.time.getTime()您可以通过调用Day.getTime()将日期时间转换为long,该函数以毫秒为单位返回long。您还可以将10分钟转换为毫秒,毫秒应为10*60*1000。现在在Day.getTime()上放置一些比较逻辑以查找下一个10分钟条目。
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;
}
}
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();
class PostsGroup {
private List<Post> posts;
public PostsGroup(List<Post> posts) {
this.posts = posts;
}
}