使用串流查找清單中的最大和最小日期
1. 概述
在本文中,我們將探討如何使用Streams
在這些物件清單中找到最大和最小日期。
2. 設定範例
Java 的原始Date
API 仍然被廣泛使用,因此我們將展示一個使用它的範例。但是,自 Java 8 以來,引入了LocalDate
,並且大多數Date
方法已被棄用。因此,我們還將展示一個使用LocalDate
的範例。
首先,讓我們建立一個包含單獨Date
屬性的基本Event
物件:
public class Event {
Date date;
// constructor, getter and setter
}
若要為Date,
我們將使用 Apache Commons 的DateUtils
方法addDays()
。為此,我們需要將最新版本的庫新增到pom.xml
中:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
我們現在可以定義三個Event
的清單:第一個發生在今天,第二個發生在明天,第三個發生在一週內:
Date TODAY = new Date();
Event TODAYS_EVENT = new Event(TODAY);
Date TOMORROW = DateUtils.addDays(TODAY, 1);
Event TOMORROWS_EVENT = new Event(TOMORROW);
Date NEXT_WEEK = DateUtils.addDays(TODAY, 7);
Event NEXT_WEEK_EVENT = new Event(NEXT_WEEK);
List<Event> events = List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT);
我們現在的目標是編寫一個方法,能夠確定NEXT_WEEK_EVENT
是此Event
清單中的最大日期。我們也將使用LocalDate
而不是Date
執行相同的操作。我們的LocalEvent
將如下所示:
public class LocalEvent {
LocalDate date;
// constructor, getter and setter
}
建置Event
清單更加簡單,因為LocalDate
已經有一個內建的plusDays()
方法:
LocalDate TODAY_LOCAL = LocalDate.now();
LocalEvent TODAY_LOCAL_EVENT = new LocalEvent(TODAY_LOCAL);
LocalDate TOMORROW_LOCAL = TODAY_LOCAL.plusDays(1);
LocalEvent TOMORROW_LOCAL_EVENT = new LocalEvent(TOMORROW_LOCAL);
LocalDate NEXT_WEEK_LOCAL = TODAY_LOCAL.plusWeeks(1);
LocalEvent NEXT_WEEK_LOCAL_EVENT = new LocalEvent(NEXT_WEEK_LOCAL);
List<LocalEvent> localEvents = List.of(TODAY_LOCAL_EVENT, TOMORROW_LOCAL_EVENT, NEXT_WEEK_LOCAL_EVENT);
3. 取得最大日期
首先,我們將使用Stream API
來串流Event
清單。然後,我們需要將Date
getter 應用於Stream
的每個元素。因此,我們將獲得一個包含事件日期的Stream
。我們現在可以使用max()
函數。這將傳Stream
中有關所提供的Comparator
最大Date
。
Date
類別實作Comparable<Date>
。因此, compareTo()
方法定義了自然日期順序。簡而言之,可以在max()
中等效地呼叫以下兩個方法:
-
Date
的compareTo()
可以透過方法引用來引用 -
Comparator
的naturalOrder()
可以直接使用
最後,我們要注意,如果給定的Event
清單為 null 或為空,我們可以直接傳回 null。這將確保我們在串流傳輸清單時不會遇到問題。
該方法最終如下所示:
Date findMaxDateOf(List<Event> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(Event::getDate)
.max(Date::compareTo)
.get();
}
或者,使用naturalOrder(),
它將顯示為:
Date findMaxDateOf(List<Event> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(Event::getDate)
.max(Comparator.naturalOrder())
.get();
}
總而言之,我們現在可以快速測試我們的方法是否為清單傳回正確的結果:
assertEquals(NEXT_WEEK, findMaxDateOf(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT);
對於LocalDate
,推理是完全相同的。 LocalDate
確實實作了ChronoLocalDate
接口,該接口擴展了Comparable<ChronoLocalDate>
。因此, LocalDate
的自然順序是由ChronoLocalDate
的compareTo()
方法定義的。
結果,該方法可以寫成:
LocalDate findMaxDateOf(List<LocalEvent> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(LocalEvent::getDate)
.max(LocalDate::compareTo)
.get();
}
或者,以完全等效的方式:
LocalDate findMaxDateOf(List<LocalEvent> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(LocalEvent::getDate)
.max(Comparator.naturalOrder())
.get();
}
我們可以編寫以下測試來確認它是否有效:
assertEquals(NEXT_WEEK_LOCAL, findMaxDateOf(List.of(TODAY_LOCAL_EVENT, TOMORROW_LOCAL_EVENT, NEXT_WEEK_LOCAL_EVENT)));
4. 取得最短日期
同樣,我們可以在Date
列表中找到最小日期:
Date findMinDateOf(List<Event> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(Event::getDate)
.min(Date::compareTo)
.get();
}
正如我們所看到的,唯一的變化是我們使用了min()
函數而不是max()
。讓我們驗證一下它是否為我們提供了三個日期中最早的日期:
@Test
void givenEventList_whenFindMinDateOf_thenReturnMinDate() {
assertEquals(TODAY, DateHelper.findMinDateOf(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT)));
}
如果我們使用LocalDate
,我們將使用此方法:
LocalDate findMaxDateOfLocalEvents(List<LocalEvent> events) {
if (events == null || events.isEmpty()) {
return null;
}
return events.stream()
.map(LocalEvent::getDate)
.max(LocalDate::compareTo)
.get();
}
再一次,我們所做的唯一更改是將max()
的呼叫替換為min()
方法的呼叫。最後我們還可以測試一下:
@Test
void givenEventList_whenFindMinDateOfWithComparator_thenReturnMaxDate() {
assertEquals(TODAY, DateHelper.findMinDateOfWithComparator(List.of(TODAYS_EVENT, TOMORROWS_EVENT, NEXT_WEEK_EVENT)));
}
5. 結論
在本教程中,我們了解如何取得物件清單中的最大或最小日期。我們使用了Date
和LocalDate
物件。
與往常一樣,可以在 GitHub 上找到程式碼。