问题:
Snack类的isExpired方法实现了什么功能?
现有相当大量的snack对象(如一个长度100万的Snack对象数组)需要执行isExpired方法,执行时候发现效率低下, 请分析原因, 并给出优化方案?
为了方便交流学习, 我把完整的题目都贴出来了, 我主要的问题是第二问, 大家有没有好的办法?
代码如下:
public class Snack {
public Snack(String name, Date expirDate){
this.name = name;
this.expireDate = expireDate;
}
private String name;
private Date expireDate;
public boolean isExpired(){
Date now = new Date();
return now.compareTo(this.expireDate) > 0 ;
}
}
天蓬老师2017-04-18 09:59:04
ご招待ありがとうございます。
これは Baidu で見つけることができます。現在の日付がオブジェクトのexpiredDateより大きい場合、trueを返します。
私のアルゴリズムはあまり良くありません。間違いがある場合は、コメントしてください。まず、オブジェクトのexpireDateが正しいかどうかを検討してください。 Orderly は二分探索の考え方から学ぶことができます。たとえば、小さいオブジェクトから大きいオブジェクトまで、オブジェクトが見つかると、後続のすべてのオブジェクトは true を返します。
高洛峰2017-04-18 09:59:04
まず、Date
オブジェクトの compareTo
メソッドの内部実装を見てみましょう。これにより、オーバーヘッドが増加します。 clone
メソッドの機能は、現在のオブジェクトが期限切れであるかどうかを判断することです。isExpired
が現在のサーバー時間より前の場合は期限切れではないと見なされ、それ以外の場合は期限切れであると見なされます。 expireDate
現在、isExpired メソッドを実行する必要があるスナック オブジェクト (長さ 100 万の Snack オブジェクトの配列など) が非常に多くあります2. この式は少し曖昧なので、2 つの状況で説明します:
2.1. 長さ 100W のスナック配列、
メソッドの走査と実行、質問は JVM メモリを調べる可能性があります。プログラムはこれら 100 万個のオブジェクトの isExpired
メソッドを 連続して 実行し (これらのオブジェクトの作成コストは無視されていると仮定します)、プログラムが実行されるたびに、新しい isExpired
オブジェクトが作成され、Date
内部で compareTo
が複製されるため、オーバーヘッドが比較的大きくなります。this.expireDate
2.2 一定期間内に多数の Snack オブジェクトが存在します。 >
メソッドを並列実行する ため、テストは同時実行性の高い処理になる可能性があります。2.1 の知識ポイントにも触れることができれば、追加のポイントを獲得できます。
個人的には2.2の確率の方が高いと思います。 isExpired
1.
が2.1
の場合、 long
または int
(精度要件が高くない場合) を使用します。次に、メソッドの外側で expireDate
をスタックできます (時間精度の要件がそれほど高くないと仮定して)。その後、 メソッド内で と Date now = new Date()
の値を比較するだけで済みます。 isExperied
2.2 now.getTime()
であり、アプリケーションがクラスター環境にデプロイされている場合、expireDate
オブジェクトは で生成できません。これは、サーバー間で時刻同期が行われていても、時刻の不一致が発生する可能性があるためです。たとえば、 、マシン A とマシン B の差が 1 秒である可能性もあります。このとき、グローバル時間ジェネレーターを使用すると、アプリケーションがこのジェネレーターを呼び出して現在のサーバー時間を取得し、比較することができます 2. ビジネスの観点から isExpired
有効期限 Date
の正確さを確認します。これは [年 | 月 | 日 | 時 | 分 | 秒 | ミリ秒] であり、精度が高ければ高いほど、ストレージと比較の戦略も異なる場合があります。
文章はかなり乱雑です。
伊谢尔伦2017-04-18 09:59:04
データ量が多い場合、isExpired()
で一つ一つの時間を取得するのは時間がかかります。
配列内の各オブジェクトの isExpired()
が同時に順次呼び出されるため、比較も同時に行われるとみなして、 isExpired()
にオーバーロード
電話をかけるときにこれを行うことができます
リーリー高洛峰2017-04-18 09:59:04
配列を優先キューに変更するたびに、ヒープの最上位要素で isExpired() を実行するだけで、パフォーマンスが O(n) から O(1) に向上します
天蓬老师2017-04-18 09:59:04
並列というものが見えてきたので、Java 8 の新しい API、並列フローを使用したいと思います (笑)。参考までに、簡単に練習してみました。
Date の従来の CompareTo メソッドを使用して比較します
Date の System.currentTimeMillis() > expiredDate.getTime()
メソッドを使用して比較します
比較を容易にするために、各比較メソッドは 5 回実行されます。同時に、各メソッドは実行に 3 つのモードを使用します。
ループ実行モード
ストリームループ実行モード
並列ストリームループ実行モード
コードは次のようになります:
リーリー最終的な実行結果は次のとおりです:
100万レベル
][2]
1000wレベル
要約すると、テストコードから判断すると、時間比較方法を変更するかどうかはあまり影響しないと感じます(ただし、並列を採用した後は影響はありません)。フロー方式では、実行効率が実際に向上しました。多数の配列またはコレクションを操作する場合、JDK は特定の環境に応じてより適切な同時実行モードを決定します。
大家讲道理2017-04-18 09:59:04
質問には「isExpiredメソッドを実行する必要のあるスナックオブジェクト(長さ100万のスナックオブジェクト配列など)が現在大量にあり、効率が低いことが判明しています」とあります。実行中"
ここには 2 つの主要な問題がありますが、どれを解決すればよいのかわかりません。
多数のオブジェクトを解決しますか?
2. 実行の非効率性を解決する。
質問 1、
10,000 個のオブジェクトの配列をクリアします。やるべきことはそれほど多くありません。
質問 2、
isExpire() メソッドで実行されたコードを削除します。このメソッドは何も行わず、実行効率が高くなります。