Date オブジェクトのリストと、ターゲット Date があります。ターゲット日付に最も近いリスト内の日付を検索したいが、ターゲット日付より前の日付のみ。
例: 2008 年 10 月 1 日 2008 年 10 月 2 日 2008 年 10 月 4 日
2008 年 10 月 3 日のターゲット日付で、2008 年 10 月 2 日を取得したい
それを行う最良の方法は何ですか?
private Date getDateNearest(List<Date> dates, Date targetDate){
return new TreeSet<Date>(dates).lower(targetDate);
}
事前に並べ替えられたリストは必要ありません。TreeSort はそれを修正します。ただし、見つからない場合は null を返すため、問題がある場合は変更する必要があります。効率もよくわかりません:P
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 になります
現在、次の方法を使用していますが、これが最も効果的な方法かどうかはわかりません。これは、既に並べ替えられたリストを想定しており、(潜在的に) リスト内のすべての日付を反復処理するためです。
private Date getDateNearest(List<Date> dates, Date targetDate){
for (Date date : dates) {
if (date.compareTo(targetDate) <= 0) return date;
}
return targetDate;
}
NavigableSet::lower
The Answer by Keegは巧妙に簡潔です。lower
インターフェイスで定義され、クラスNavigableSet
で実装されたメソッドを利用するという考え方があります。TreeSet
しかし、他の回答と同様に、Java の初期バージョンにバンドルされている古い時代遅れの日時クラスを使用します。以下は、java.timeクラスを使用した更新バージョンです。
古い質問と回答は、日付と時刻のjava.util.Date
両方を表す UTC のタイムライン上の瞬間であるか、時刻を持たないふりをしながら util.Date をぎこちなく拡張する のいずれかを使用しています。紛らわしい混乱。java.sql.Date
これらの厄介な古いクラスは、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
ヒント: これらの月と日の数字は、先行ゼロで埋めてください。これにより、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.
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 );
}
}
JodaTime APIを見たことがありますか?このような機能が利用可能だったことを思い出しているようです。