问题:
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 ;
}
}
ご招待ありがとうございます。
これは Baidu で見つけることができます。現在の日付がオブジェクトのexpiredDateより大きい場合、trueを返します。
私のアルゴリズムはあまり良くありません。間違いがある場合は、コメントしてください。まず、オブジェクトのexpireDateが正しいかどうかを検討してください。 Orderly は二分探索の考え方から学ぶことができます。たとえば、小さいオブジェクトから大きいオブジェクトまで、オブジェクトが見つかると、後続のすべてのオブジェクトは true を返します。
まず、
1.Date
オブジェクトのcompareTo
メソッドの内部実装を見てみましょう。これにより、オーバーヘッドが増加します。clone
メソッドの機能は、現在のオブジェクトが期限切れであるかどうかを判断することです。
2. この式は少し曖昧なので、2 つの状況で説明します:isExpired
が現在のサーバー時間より前の場合は期限切れではないと見なされ、それ以外の場合は期限切れであると見なされます。expireDate
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.2now.getTime()
であり、アプリケーションがクラスター環境にデプロイされている場合、expireDate
オブジェクトは で生成できません。これは、サーバー間で時刻同期が行われていても、時刻の不一致が発生する可能性があるためです。たとえば、 、マシン A とマシン B の差が 1 秒である可能性もあります。このとき、グローバル時間ジェネレーターを使用すると、アプリケーションがこのジェネレーターを呼び出して現在のサーバー時間を取得し、比較することができます 2. ビジネスの観点からisExpired
有効期限Date
の正確さを確認します。これは [年 | 月 | 日 | 時 | 分 | 秒 | ミリ秒] であり、精度が高ければ高いほど、ストレージと比較の戦略も異なる場合があります。文章はかなり乱雑です。
データ量が多い場合、
を追加します。 リーリーisExpired()
で一つ一つの時間を取得するのは時間がかかります。配列内の各オブジェクトの
isExpired()
が同時に順次呼び出されるため、比較も同時に行われるとみなして、isExpired()
にオーバーロード電話をかけるときにこれを行うことができます
リーリー
と時間を比較しますSystem.currentTimeMillis()
リーリー
配列を優先キューに変更するたびに、ヒープの最上位要素で isExpired() を実行するだけで、パフォーマンスが O(n) から O(1) に向上します
並列というものが見えてきたので、Java 8 の新しい API、並列フローを使用したいと思います (笑)。参考までに、簡単に練習してみました。
Date の従来の CompareTo メソッドを使用して比較します
Date の
System.currentTimeMillis() > expiredDate.getTime()
メソッドを使用して比較します比較を容易にするために、各比較メソッドは 5 回実行されます。同時に、各メソッドは実行に 3 つのモードを使用します。
ループ実行モード
ストリームループ実行モード
並列ストリームループ実行モード
コードは次のようになります:
リーリー最終的な実行結果は次のとおりです:
100万レベル
][2]
1000wレベル
要約すると、テストコードから判断すると、時間比較方法を変更するかどうかはあまり影響しないと感じます(ただし、並列を採用した後は影響はありません)。フロー方式では、実行効率が実際に向上しました。多数の配列またはコレクションを操作する場合、JDK は特定の環境に応じてより適切な同時実行モードを決定します。
最適化ポイントは 2 つあります
1: Date オブジェクトの作成
2.compareTo() メソッド
質問には「isExpiredメソッドを実行する必要のあるスナックオブジェクト(長さ100万のスナックオブジェクト配列など)が現在大量にあり、効率が低いことが判明しています」とあります。実行中"
ここには 2 つの主要な問題がありますが、どれを解決すればよいのかわかりません。
多数のオブジェクトを解決しますか?
2. 実行の非効率性を解決する。
質問 1、
10,000 個のオブジェクトの配列をクリアします。やるべきことはそれほど多くありません。
質問 2、
isExpire() メソッドで実行されたコードを削除します。このメソッドは何も行わず、実行効率が高くなります。