2016-12-08 8 views
1

タイムスタンプ付きのイベントの高頻度ストリームを処理していますが、オーダーの保証はありません(時間の90%が順序付けされています)。私はこれらのイベントを私のプログラムに何度か保存する必要があります。私の計算のパフォーマンスを最適化するためには、順序付きリストをキャッシュすることでオーダーを保証できれば、はるかに簡単です。だから私が探しているのは、挿入と反復が速く、重複を許す順序付けられたデータ構造です。私はインターネット上で発見したすべての命題の中で

は、私が試してみました:
- TreeSetの - 私は重複したタイムスタンプを持っているかもしれないので>は動作しません
- 優先度つきキュー - イテレータが優先順位

を保証するものではありませんので>は動作しません

Javaタイムオーダーのデータ構造

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

しかし、私は本当に悪いパフォーマンスを得る両方のバージョン: 9/10以降のイベントはよく私はaddメソッドの修正バージョンと基本のArrayListを使用することができると思った順に並べられます。

提案がありますか?

+1

データ構造内の要素にランダムアクセスする必要がありますか、それとも常にすべてを繰り返していますか? –

+0

独自のヒープデータ構造を使用してみませんか? – SMA

+2

同じタイムスタンプのイベントが「同じ」ものとして表示されないようにするカスタムコンパレータを作成することは可能でしょうか? – GhostCat

答えて

1

私はあなたが既にそれを解雇したことを知っていますが、私はまだTreeSetを提案します。

実際にタイムスタンプが重複することは問題ありません。唯一の条件は、比較器がと一致するであることです。これ以上何もない。

はい、最初のアプローチでは、イベントのタイムスタンプを比較すると、それはおそらくequalsと一貫しません。しかし、と他ののイベントのフィールドを比較すると、これはequalsと一貫しています。

これはもちろん、タイムスタンプがEのイベントクラスの一部であることを前提としています。

1

問題の説明から、ある期間にわたってイベントコレクションに対して反復処理を行うことができれば、問題の厳密な順序は必須ではないことがわかります。また、あなたが言及するデータの種類は、複数のクライアントノードが1つの集中サーバ(複数のサービスからのログ/イベントの蓄積)にデータを送信しているようです。

これが当てはまる場合、タイムスタンプに対応するイベントが特定のバケットにのみ入るバケットの単純な配列を使用して探索できます。タイムスタンプに非常に近いすべてのイベントが同じバケットに分類されるので、イベント間で部分的な順序を取ることができます。

例:最後の1分(60秒)のデータが必要な場合は、1秒間に1つずつ60個のバケットを定義し、それらを回転し続けることができます。イベントタイムスタンプ2016-12-08 19:59:29.538331は29番目のバケットに移動します(インデックスは0から始まり、すべてのイベントの秒数を取ると仮定します)。 1分が経過すると、i番目のバケットの過去のデータを消去し、新しいバケットを作成し直します。したがって、2016-12-08 20:00:00.129845に、0番目のバケットは空の配列にリセットされます。

タイムスタンプのイベントの頻度が高いストリームがあるため、空のバケットの可能性は最小限に抑えられます。あなたの正確な要件に基づいて必要なバケツの数を調整することができます。