java - 一道优化的小代码题目, 面试题
巴扎黑
巴扎黑 2017-04-18 09:57:04
0
9
840

问题:

  1. Snack类的isExpired方法实现了什么功能?

  2. 现有相当大量的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 ;
    }

}
巴扎黑
巴扎黑

全員に返信(9)
Peter_Zhu

ご招待ありがとうございます。

  1. これは Baidu で見つけることができます。現在の日付がオブジェクトのexpiredDateより大きい場合、trueを返します。

  2. 私のアルゴリズムはあまり良くありません。間違いがある場合は、コメントしてください。まず、オブジェクトのexpireDateが正しいかどうかを検討してください。 Orderly は二分探索の考え方から学ぶことができます。たとえば、小さいオブジェクトから大きいオブジェクトまで、オブジェクトが見つかると、後続のすべてのオブジェクトは true を返します。

いいねを押す +0
小葫芦

まず、Date オブジェクトの compareTo メソッドの内部実装を見てみましょう。これにより、オーバーヘッドが増加します。 clone

1.

メソッドの機能は、現在のオブジェクトが期限切れであるかどうかを判断することです。isExpired が現在のサーバー時間より前の場合は期限切れではないと見なされ、それ以外の場合は期限切れであると見なされます。 expireDate

現在、isExpired メソッドを実行する必要があるスナック オブジェクト (長さ 100 万の Snack オブジェクトの配列など) が非常に多くあります

2. この式は少し曖昧なので、2 つの状況で説明します:

2.1. 長さ 100W のスナック配列、
メソッドの走査と実行、質問は JVM メモリを調べる可能性があります。プログラムはこれら 100 万個のオブジェクトの isExpired メソッドを 連続して 実行し (これらのオブジェクトの作成コストは無視されていると仮定します)、プログラムが実行されるたびに、新しい isExpired オブジェクトが作成され、Date 内部で compareTo が複製されるため、オーバーヘッドが比較的大きくなります。this.expireDate2.2 一定期間内に多数の Snack オブジェクトが存在します。 >
メソッドを並列実行する ため、テストは同時実行性の高い処理になる可能性があります。2.1 の知識ポイントにも触れることができれば、追加のポイントを獲得できます。 個人的には2.2の確率の方が高いと思います。 isExpired

このコードについての私の最適化の理解について話します:

1.

2.1
の場合、 long または int (精度要件が高くない場合) を使用します。次に、メソッドの外側で expireDate をスタックできます (時間精度の要件がそれほど高くないと仮定して)。その後、 メソッド内で Date now = new Date() の値を比較するだけで済みます。 isExperied2.2 now.getTime() であり、アプリケーションがクラスター環境にデプロイされている場合、expireDate オブジェクトは で生成できません。これは、サーバー間で時刻同期が行われていても、時刻の不一致が発生する可能性があるためです。たとえば、 、マシン A とマシン B の差が 1 秒である可能性もあります。このとき、グローバル時間ジェネレーターを使用すると、アプリケーションがこのジェネレーターを呼び出して現在のサーバー時間を取得し、比較することができます 2. ビジネスの観点から isExpired 有効期限 Date の正確さを確認します。これは [年 | 月 | 日 | 時 | 分 | 秒 | ミリ秒] であり、精度が高ければ高いほど、ストレージと比較の戦略も異なる場合があります。
文章はかなり乱雑です。

いいねを押す +0
伊谢尔伦

データ量が多い場合、isExpired()で一つ一つの時間を取得するのは時間がかかります。
配列内の各オブジェクトの isExpired() が同時に順次呼び出されるため、比較も同時に行われるとみなして、 isExpired() にオーバーロード

を追加します。 リーリー

電話をかけるときにこれを行うことができます

リーリー
いいねを押す +0
小葫芦

System.currentTimeMillis()

と時間を比較します
いいねを押す +0
Peter_Zhu

リーリー

いいねを押す +0
小葫芦

配列を優先キューに変更するたびに、ヒープの最上位要素で isExpired() を実行するだけで、パフォーマンスが O(n) から O(1) に向上します

いいねを押す +0
Peter_Zhu

並列というものが見えてきたので、Java 8 の新しい API、並列フローを使用したいと思います (笑)。参考までに、簡単に練習してみました。

  1. Date の従来の CompareTo メソッドを使用して比較します

  2. Date の System.currentTimeMillis() > expiredDate.getTime() メソッドを使用して比較します

比較を容易にするために、各比較メソッドは 5 回実行されます。同時に、各メソッドは実行に 3 つのモードを使用します。

  1. ループ実行モード

  2. ストリームループ実行モード

  3. 並列ストリームループ実行モード

コードは次のようになります:

リーリー

最終的な実行結果は次のとおりです:
100万レベル

][2]

1000wレベル

要約すると、テストコードから判断すると、時間比較方法を変更するかどうかはあまり影響しないと感じます(ただし、並列を採用した後は影響はありません)。フロー方式では、実行効率が実際に向上しました。多数の配列またはコレクションを操作する場合、JDK は特定の環境に応じてより適切な同時実行モードを決定します。

いいねを押す +0
迷茫

最適化ポイントは 2 つあります
1: Date オブジェクトの作成
2.compareTo() メソッド

いいねを押す +0
大家讲道理

質問には「isExpiredメソッドを実行する必要のあるスナックオブジェクト(長さ100万のスナックオブジェクト配列など)が現在大量にあり、効率が低いことが判明しています」とあります。実行中"

ここには 2 つの主要な問題がありますが、どれを解決すればよいのかわかりません。

  1. 多数のオブジェクトを解決しますか?
    2. 実行の非効率性を解決する。

質問 1、
10,000 個のオブジェクトの配列をクリアします。やるべきことはそれほど多くありません。

質問 2、
isExpire() メソッドで実行されたコードを削除します。このメソッドは何も行わず、実行効率が高くなります。

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート