2015-12-22 11 views
6

मेरे पास ऑब्जेक्ट्स की एक स्ट्रीम है जिसे मैं निम्न तरीके से एकत्र करना चाहता हूं।जावा 8 जटिल कस्टम कलेक्टर

मान लीजिए कि हम मंच पदों संभाल रहे हैं:

class Post { 
    private Date time; 
    private Data data 
} 

मैं जो समूहों अवधि द्वारा पदों एक सूची बनाना चाहते हैं। यदि एक्स मिनट के लिए कोई पोस्ट नहीं थी, तो नया समूह बनाएं।

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

मैं एक List<PostGroups> पदों अंतराल के आधार पर वर्गीकृत युक्त प्राप्त करना चाहते हैं।

उदाहरण: अंतराल 10 मिनट।

पोस्ट:

[ 
{posts : [{time:x, data:{}}, {time:x + 3, data:{}}, {time:x+ 12, data:{}]]}, 
{posts : [{time:x+ 45, data:{}]} 
] 
  • सूचना है कि पहले समूह चली तक एक्स + 22. तब एक नई पोस्ट में प्राप्त किया गया था:

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

    मैं पदों समूह की एक सूची प्राप्त करना चाहते हैं एक्स +45.

क्या यह संभव है?

+1

आप डेट.getTime() को कॉल करके दिनांक समय को लंबे समय तक परिवर्तित कर सकते हैं जो मिलीसेकंड में वर्तमान समय को लंबे समय तक बताता है। आप 10 मिनट को मिलीसेकंड में भी परिवर्तित कर सकते हैं जो 10 * 60 * 1000 होना चाहिए। अब अगले 10 मिनट प्रविष्टियों को खोजने के लिए Day.getTime() पर कुछ तुलनात्मक तर्क डालें। –

उत्तर

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; 
    } 

} 
2

यह समस्या आसानी से अपने StreamEx पुस्तकालय की groupRuns पद्धति का उपयोग करके हल किया जा सकता:

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; 
    } 
} 

StreamEx.groupRuns विधि एक BiPredicate लेता है जो दो आसन्न इनपुट तत्वों पर लागू होता है और यदि उन्हें एक साथ समूहीकृत किया जाना चाहिए तो सत्य वापस आते हैं। यह विधि सूचियों की धारा बनाता है जहां प्रत्येक सूची समूह का प्रतिनिधित्व करती है। यह विधि आलसी है और समांतर धाराओं के साथ ठीक काम करती है।

संबंधित मुद्दे