Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/379.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 基于时间的分组_Java_Algorithm - Fatal编程技术网

Java 基于时间的分组

Java 基于时间的分组,java,algorithm,Java,Algorithm,我有以下问题: 我有一个对象列表(包含一个日期属性),大小为S(通常S会达到200k左右,但有时可能会达到一百万) 我需要根据以下条件筛选列表: 只有从日期属性开始,在时间间隔T内的列表X事件中才能找到项目,该项目才必须保留在最终列表中 考虑到大量的列表以及低效的解决方案可能会产生哪些性能问题,请您告诉我解决此问题的最佳方法/算法 谢谢 PS:实现是用JAVA实现的,我不认为我完全理解您的问题,但是如果列表按日期排序,您应该能够确定以下X项是否都在时间间隔t内,否则请删除它们 如果X变高,您

我有以下问题:

我有一个对象列表(包含一个日期属性),大小为S(通常S会达到200k左右,但有时可能会达到一百万)

我需要根据以下条件筛选列表:

  • 只有从日期属性开始,在时间间隔T内的列表X事件中才能找到项目,该项目才必须保留在最终列表中
考虑到大量的列表以及低效的解决方案可能会产生哪些性能问题,请您告诉我解决此问题的最佳方法/算法

谢谢


PS:实现是用JAVA实现的,我不认为我完全理解您的问题,但是如果列表按日期排序,您应该能够确定以下X项是否都在时间间隔t内,否则请删除它们

如果X变高,您可能会考虑使用不同的排序结构,例如<代码>树贴图,其中键是日期。然后你可以这样做:

SortedMap<Date, YourObject> map = ...;//left for you

int numEventsInInterval = map.subMap( intervalStart, intervalEnd ).size();
SortedMap=//留给你的
int numEventsInInterval=map.subMap(intervalStart,intervalEnd.size();
您需要:

class Foo { Date date; } 
class Event { Period period; }
class Period { Date start, end; }

List<Foo> foos = ...
List<Event> events = ...
Period p = new Period(...)

[pseudo-code]
foreach foo in foos: 
    eventsAfterFoo = findEventsAfter(foo.date, events);
    c = 0;
    foreach event in eventsAfterFoo:
        if(event.isInPeriod(p)) c++
    if(c >= X) 
        finalList.add(foo) 
class Foo{Date;}
类事件{Period Period;}
类周期{日期开始,结束;}
列表foos=。。。
列出事件=。。。
期间p=新期间(…)
[伪代码]
foos中的foreach foo:
eventsAfterFoo=findEventsAfter(foo.date,events);
c=0;
eventsAfterFoo中的foreach事件:
If(事件IsI期(p))C++
如果(c>=X)
finalList.add(foo)
对于大量元素,您肯定会使用数据库简化您的解决方案,即使是像HSQL这样的非主流数据库


您当然可以将列表拆分为不同机器上的不同VM,唯一的共享/只读列表是“事件”

在完整列表中遍历长度为X的子列表

在每次迭代中:

如果sublist.tail.date-sublist.head.date>T,则标记sublist.head以丢弃


不幸的是,你最终可能会放弃一些资格赛,但这是可以解决的。

我可能完全错了,但我认为人们忽略了一个事实,即你的标题使用了“分组”而不是“筛选”,以及“从日期属性开始”的部分。以下是我对你的问题的看法:

  • 您有一个源列表L,其中包含具有时间戳属性t的I类型的项
  • 您希望构造一个目标列表T,其中包含来自L的项(可能顺序相同)
  • 您有一些半径r,表示为时间单位(毫秒、秒、分钟…)
  • 您有一些正整数阈值l(这里没有字母了)
  • 当且仅当L中有L个或多个时间戳在区间[i.T-r,i.T+r]内的项目时,L中的项目i应放置在T中
假设列表没有排序,迭代列表并计算每个条目间隔内的项数将非常昂贵。这将导致O(n²)性能

如果T中项目的顺序可能与L中项目的顺序不同,则以下是有效的解决方案:

  • 对L中的项目进行排序。如果项目类型I实现了
    Comparable
    接口,并且按照时间戳进行排序,那么它将很简单。否则,您可能需要实现一个对timestamp属性进行排序的
    比较器。排序的性能不能比O(n*logn)更好,所以这是目前的底线

  • 制作三个索引:s(开始)、e(结束)、c(当前项)

  • 使用索引c迭代排序列表。对于每个条目,请执行以下操作:

    3.1从索引s开始,计算不再落在“半径”内的项目数。也就是说,有多少项的时间戳小于索引c处的项的时间戳减去时间半径。将该值添加到索引s。这使得它指向半径范围内的“最早”项目

    3.2从索引e开始,检查排序列表中的项目是否在半径范围内。让e指向最后一项

    3.3取值(e-s)。如果它低于阈值l,则表示索引c处的项通过了过滤器。否则,它不会

    3.4增量c。如果c现在大于e,则也增加e

  • 就这样。第3步检查排序列表中的每个项目一次,这样就得到了O(n)性能。最坏情况取决于时间戳和半径。不是每次都从列表的开头开始搜索下限,而是从后面的索引s开始搜索。不是每次都从c开始搜索上限,而是从前导索引e开始搜索。因此,我认为最坏情况下的性能仍然是O(n),因为s和e也只能遍历列表一次。假设您有100个条目,并且从条目3您发现所有剩余条目都在半径范围内(即,e变为99),您将不必进一步检查

    在一个O(n*logn)步骤和一个O(n)步骤中,摊销绩效变为O(n*logn)。似乎可以接受

    请注意,如果筛选列表必须保持原始项目顺序,则需要执行其他步骤。在这种情况下,可以使用某种索引列表


    编辑:我刚刚意识到你的字面意思可能是“从开始”,所以如果是这样的话,只需忽略尾随索引s,只处理前导索引e。除采用(e-c)而不是(e-s)外,该算法在其他方面保持不变。我在预编辑版本中也有一些“框架列表”,这显然是无稽之谈,因为索引足以计算所需的数量。

    您可以通过监视器“流式”对象(我称之为事件),监视器用所需属性标记事件

    例如:

    public class EventMonitor {
    
        private int minimumGroupSize;
        private long window;
    
        private LinkedList<Event> events = new LinkedList<Event>();
    
        public EventMonitor(int minimumGroupSize, long window) {
            this.minimumGroupSize = minimumGroupSize;
            this.window = window;
        }
    
        public void handle(Event newest) {
    
            System.out.println(newest);
            events.addLast(newest);
            if (events.size() == minimumGroupSize) {
                Event oldest = events.peekFirst();
                if (newest.getTimestamp() - oldest.getTimestamp() < window) {
                    System.out.println("Group starter: " + oldest);
                }
                events.removeFirst();
            }
        }
    
        public static class Event {
            private final long timestamp;
    
            Event(long timestamp) {
                this.timestamp = timestamp;
            }
    
            public long getTimestamp() {
                return timestamp;
            }
    
            public String toString() {
                return String.valueOf(timestamp);
            }
        }
    
        public static void main(String[] args) {
    
            EventMonitor monitor = new EventMonitor(5, 15);
            feedEventData(monitor);
        }
    
        private static void feedEventData(EventMonitor monitor) {
            long timestamp = 0;
            for (int i = 0; i < 20; i++) {
    
                long interval = 1 + (long) (Math.random() * 10);
                timestamp = timestamp + interval;
                monitor.handle(new Event(timestamp));
            }
        }
    }
    
    公共类事件监视器{
    私有int最小组大小;
    私人长窗;
    专用链路