Java时序数据结构

Java时序数据结构,java,optimization,data-structures,Java,Optimization,Data Structures,我正在处理时间戳事件的高频流,没有订购保证(订购了90%的时间)。我需要在程序中存储这些事件(用于缓存)。为了优化我的计算性能(主要需要对事件集合进行迭代),如果我可以通过缓存有序列表来保证顺序,那么对我来说会容易得多。所以我要寻找的是一个有序的数据结构,它可以快速插入和迭代,并允许重复 在我在互联网上找到的所有主张中,我尝试过: -TreeSet->不起作用,因为我可能有重复的时间戳 -PriorityQueue->不起作用,因为迭代器不保证优先级顺序 由于9/10事件的顺序很好,我想我可以使

我正在处理时间戳事件的高频流,没有订购保证(订购了90%的时间)。我需要在程序中存储这些事件(用于缓存)。为了优化我的计算性能(主要需要对事件集合进行迭代),如果我可以通过缓存有序列表来保证顺序,那么对我来说会容易得多。所以我要寻找的是一个有序的数据结构,它可以快速插入和迭代,并允许重复

在我在互联网上找到的所有主张中,我尝试过:
-TreeSet->不起作用,因为我可能有重复的时间戳
-PriorityQueue->不起作用,因为迭代器不保证优先级顺序

由于9/10事件的顺序很好,我想我可以使用一个基本的ArrayList和一个修改版本的add方法:

public class TimeOrderedArrayList<E> extends ArrayList<E>{

private long lastTs;
private Comparator<E> comparator;
private TimeGetter<E> tsgetter;

public TimeOrderedArrayList (Comparator<E> comparator, TimeGetter<E> tsgetter) {
    super();
    this.comparator = comparator;
    this.tsgetter = tsgetter;
    this.lastTs = Long.MIN_VALUE;
}


@Override
public boolean add(E e) {
    if (tsgetter.getTime(e) >= lastTs) {
        lastTs = tsgetter.getTime(e);
        return super.add(e);
    } else {

        // VERSION 1
        int index = super.size()-1;
        while (tsgetter.getTime(super.get(index))>tsgetter.getTime(e) && index > 0) {
            index--;
        }
        super.add(index, e);

        // VERSION 2
        int index = Collections.binarySearch(this, e, comparator);
        super.add(index>-1 ? index : -index-1,e);
        return true;
    }
}

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean result = super.addAll(c);
    super.sort(comparator);
    return result;
}
}
公共类TimeOrderedArrayList扩展了ArrayList{
私人长裤;
专用比较器;
私人计时器;
公共TimeOrderedArrayList(比较器比较器、TimeGetter tsgetter){
超级();
这个比较器=比较器;
this.tsgetter=tsgetter;
this.lastTs=Long.MIN_值;
}
@凌驾
公共布尔加法(E){
if(tsgetter.getTime(e)>=lastTs){
lastTs=tsgetter.getTime(e);
返回super.add(e);
}否则{
//版本1
int index=super.size()-1;
而(tsgetter.getTime(super.get(index))>tsgetter.getTime(e)和&index>0){
索引--;
}
super.add(索引e);
//版本2
int index=Collections.binarySearch(this,e,comparator);
super.添加(索引>-1?索引:-索引-1,e);
返回true;
}
}
@凌驾

public boolean addAll(Collection我知道您已经取消了它,但我仍然建议您使用
TreeSet

拥有重复的时间戳实际上没有问题。唯一的条件是比较器与equals一致。仅此而已

是的,在第一种方法中,如果你只是比较事件的时间戳,那么这可能与equals不一致。但是如果你也比较事件的其他字段,那么这将与equals一致


当然,这是假设时间戳是事件类
E
的一部分。

从问题描述中,我认为,只要您可以在一段时间内对事件集合进行迭代,问题就不必严格排序。此外,您提到的数据类型似乎是多个客户端节点将数据发送到一个集中式服务器(可能是来自多个服务的日志/事件累积)

如果是这种情况,您可以使用一个简单的bucket数组进行探索,其中与时间戳相对应的事件只进入一个特定的bucket。您将确保所有时间戳非常接近的事件都被分类到相同的bucket中,这样您就可以实现事件之间的部分顺序

例如:如果您需要最近1分钟(60秒)的数据,您可以定义60个存储桶,每秒钟一个,并继续旋转它们。时间戳为
2016-12-08 19:59:29.538331的事件将转到第29个存储桶(假设指数从0开始,并且您以每个事件的秒为底)。一分钟后,只需清除第i个存储桶的过去数据,然后重新开始构建。因此,在
2016-12-08 20:00:00.129845
,第0个存储桶将重置为空数组


由于时间戳事件的频率很高,因此空存储桶等的可能性很小。您可以根据具体要求调整所需存储桶的数量。

您需要随机访问数据结构中的元素,还是总是遍历所有元素?为什么不使用您自己的堆数据结构?Wo是否可以编写一个自定义比较器,只需确保具有相同时间戳的事件不会显示为“相同”事件?@matiaselgart否,我只需要迭代!理想情况下,范围也会很大:)有什么想法吗?如果您只需要迭代,而不需要随机访问,那么基于
LinkedList
的实现将比
ArrayList
更好,因为随机插入的成本要低得多。