6

Date オブジェクトのリストと、ターゲット Date があります。ターゲット日付に最も近いリスト内の日付を検索したいが、ターゲット日付より前の日付のみ。

例: 2008 年 10 月 1 日 2008 年 10 月 2 日 2008 年 10 月 4 日

2008 年 10 月 3 日のターゲット日付で、2008 年 10 月 2 日を取得したい

それを行う最良の方法は何ですか?

4

6 に答える 6

6
private Date getDateNearest(List<Date> dates, Date targetDate){
    return new TreeSet<Date>(dates).lower(targetDate);
}

事前に並べ替えられたリストは必要ありません。TreeSort はそれを修正します。ただし、見つからない場合は null を返すため、問題がある場合は変更する必要があります。効率もよくわかりません:P

于 2008-10-09T08:34:15.213 に答える
6

Sietse de Kaper ソリューションは、に並べ替えられたリストを想定しています。間違いなく、最も自然なものではありません。

Java の自然な並べ替え順序は、昇順の自然な順序に従います。(Collection.sort http://java.sun.com/j2se/1.5.0/docs/api/java/util/Collections.html#sort(java.util.List)ドキュメントを参照)

あなたの例から、

目標日 = 2008-10-03
リスト = 2008 年 10 月 1 日 2008 年 10 月 2 日 2008 年 10 月 4 日

別の開発者が単純なアプローチであなたのメソッドを使用すると、期待されていない 2008-10-01 が返されます

  • リストの順序について推測しないでください。
  • パフォーマンス上の理由で必要な場合は、最も自然な規則 (昇順で並べ替え) に従うようにしてください。
  • 本当に別の規則に従わなければならない場合は、それを完全に文書化する必要があります。

    private Date getDateNearest(List<Date> dates, Date targetDate){
      Date returnDate = targetDate
      for (Date date : dates) {
        // if the current iteration'sdate is "before" the target date
        if (date.compareTo(targetDate) <= 0) {
          // if the current iteration's date is "after" the current return date
          if (date.compareTo(returnDate) > 0){
            returnDate=date;
          }
        }
      }  
      return returnDate;
    }
    

    編集 - Treeset の回答も気に入っていますが、データを並べ替えてから検索するのと同等であるため、少し遅くなる可能性があると思います => nlog(n) 並べ替えのために、ドキュメントはアクセス用に log(n) であることを示唆しているため、それは nlog(n)+log(n) 対 n になります

  • 于 2008-10-09T09:07:51.510 に答える
    2

    現在、次の方法を使用していますが、これが最も効果的な方法かどうかはわかりません。これは、既に並べ替えられたリストを想定しており、(潜在的に) リスト内のすべての日付を反復処理するためです。

    private Date getDateNearest(List<Date> dates, Date targetDate){
      for (Date date : dates) {
        if (date.compareTo(targetDate) <= 0) return date;
      }
    
      return targetDate;
    }
    
    于 2008-10-09T07:54:51.487 に答える
    1

    NavigableSet::lower

    The Answer by Keegは巧妙に簡潔です。lowerインターフェイスで定義され、クラスNavigableSetで実装されたメソッドを利用するという考え方があります。TreeSet

    しかし、他の回答と同様に、Java の初期バージョンにバンドルされている古い時代遅れの日時クラスを使用します。以下は、java.timeクラスを使用した更新バージョンです。

    古い質問と回答は、日付時刻のjava.util.Date両方を表す UTC のタイムライン上の瞬間であるか、時刻を持たないふりをしながら util.Date をぎこちなく拡張する のいずれかを使用しています。紛らわしい混乱。java.sql.Date

    java.time

    これらの厄介な古いクラスは、Java 8 以降に組み込まれたjava.timeクラスに取って代わられました。Oracle チュートリアルを参照してください。機能の多くは、 ThreeTen-Backportで Java 6 および 7 にバックポートされ、さらにThreeTenABPで Android に適合されています。

    LocalDate

    このLocalDateクラスは、時刻とタイム ゾーンのない日付のみの値を表します。ZoneIdこれらのオブジェクトはタイム ゾーンを保存しませんが、現在の日付を決定するにはタイム ゾーン ( ) が重​​要であることに注意してください。任意の時点で、日付はタイム ゾーンによって世界中で異なります。

    ZoneId zoneId = ZoneId.of( "America/Montreal" );
    LocalDate today = LocalDate.now( zoneId );  // 2016-06-25
    

    ISO8601

    ヒント: これらの月と日の数字は、先行ゼロで埋めてください。これにより、ISO 8601標準の日時形式に準拠します。これらの形式は、日時値を表す文字列を解析/生成するときに、java.time でデフォルトで使用されます。

    2008-10-01ではなく使用して2008-10-1ください。パディングが不可能な場合は、 を使用して解析しDateTimeFormatterます。

    NavigableSet dates = new TreeSet( 3 );
    dates.add( LocalDate.parse( "2008-10-01" );
    dates.add( LocalDate.parse( "2008-10-02" );
    dates.add( LocalDate.parse( "2008-10-04" );
    LocalDate target = LocalDate.parse( "2008-10-03" );
    LocalDate hit = dates.lower( target );
    // Reminder: test for `null == hit` to see if anything found.
    
    于 2016-06-25T21:36:33.463 に答える
    1

    Keeg からの回答は 1.5 の 1.6 で有効ですが、lower() メソッドはありません (1.5 に対して開発するのは残念です :-( )

    これは1.5で動作します

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.TreeSet;
    
    public class GetNearestDate {
    
      public static void main( String[] args ) throws ParseException {
    
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat( "dd.MM.yyyy HH:mm:ss" );
    
        List< Date > otherDates = Arrays.asList( new Date[]{
          simpleDateFormat.parse( "01.01.2008 01:00:00" ) ,
          simpleDateFormat.parse( "01.01.2008 01:00:02" ) } );
        System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:00" ).equals(
          get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:01" ) ) ) );
        System.out.println( simpleDateFormat.parse( "01.01.2008 01:00:02" ).equals(
          get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:03" ) ) ) );
        System.out.println( null == get( otherDates , simpleDateFormat.parse( "01.01.2008 01:00:00" ) ) );
      }
    
      public static Date get( List< Date > otherDates , Date dateToApproach ) {
        final TreeSet< Date > set = new TreeSet< Date >( otherDates );
        set.add( dateToApproach );
        final ArrayList< Date > list = new ArrayList< Date >( set );
        final int indexOf = list.indexOf( dateToApproach );
        if ( indexOf == 0 )
          return null;
        return list.get( indexOf - 1 );
      }
    
    }
    
    于 2008-10-09T09:08:05.770 に答える
    0

    JodaTime APIを見たことがありますか?このような機能が利用可能だったことを思い出しているようです。

    于 2008-10-10T03:32:17.787 に答える