您好,我正在處理一個場景,我需要使用 Java 8 的基于貨幣的最新時間戳資料。
假設我正在請求美元貨幣,那么我應該獲得所有日期的所有美元資料,時間戳最少。
class Currency{
private Integer id;
private String name;
private LocalDateTime lastReceived;
}
記錄在資料庫中如下。
ID NAME LAST_RECEIVED
-- ---- -------------
1 USD 18-MAY-22 09.04.01.545899000 AM
2 USD 18-MAY-22 08.04.01.545899000 AM
3 USD 19-MAY-22 08.04.01.545899000 AM
4 USD 20-MAY-22 08.04.01.545899000 AM
5 USD 20-MAY-22 11.04.01.545899000 AM
6 BUSD 18-MAY-22 08.04.01.545899000 AM
Expected:
ID NAME LAST_RECEIVED
-- ---- -------------
1 USD 18-MAY-22 09.04.01.545899000 AM
3 USD 19-MAY-22 08.04.01.545899000 AM
5 USD 20-MAY-22 11.04.01.545899000 AM
我試過了,假設我請求美元資料,
List<Currency> listCurrency = repo.getAllDataBasedOnCurrency("USD");
listCurrency.stream().sorted(Comparator.comparing(Currency::getLastReceived).reversed()).collect(Collectors.toList());
// But here I want latest received Data for a single date.
uj5u.com熱心網友回復:
看來您應該按貨幣和日期分組,然后按最大(最近)時間戳進行選擇,這會生成一個地圖,然后您可以使用地圖values()來構建串列。
因此,貨幣名稱和日期的串列可以用作映射中的鍵,并且Collectors.collectingAndThen需要將Optional結果Collectors.maxBy轉換為貨幣實體:
List<Currency> lastByDate = new ArrayList<>(data
.stream() // Stream<Currency>
.collect(Collectors.groupingBy(
// key = List<Serializable & Comparable<? extends Comparable<?>>>
curr -> Arrays.asList(curr.getName(), curr.getLastReceived().toLocalDate()),
Collectors.collectingAndThen(
Collectors.maxBy(Comparator.comparing(Currency::getLastReceived)),
Optional::get // Optional<Currency> -> Currency
)
)) // Map<List<...>, Currency>
.values()
);
如果需要排序串列,可以通過對以下流進行排序來檢索它values:
List<Currency> sortedByDateAndCurr = data
.stream()
.collect(Collectors.groupingBy(
curr -> Arrays.asList(curr.getName(), curr.getLastReceived().toLocalDate()),
Collectors.collectingAndThen(
Collectors.maxBy(Comparator.comparing(Currency::getLastReceived)),
Optional::get
)
))
.values()
.stream()
.sorted(
Comparator.comparing(Currency::getLastReceived)
.thenComparing(Currency::getName)
)
.collect(Collectors.toList());
或者只是對未排序的串列進行排序:
lastByDate.sort(
Comparator.comparing(Currency::getLastReceived)
.thenComparing(Currency::getName)
);
對于特定貨幣(USD如
List<Currency> lastUSDByDate = new ArrayList<>(data
.stream()
.filter(curr -> "USD".equalsIgnoreCase(curr.getName()))
.collect(Collectors.groupingBy(
curr -> curr.getLastReceived().toLocalDate(),
Collectors.collectingAndThen(
Collectors.maxBy(Comparator.comparing(Currency::getLastReceived)),
Optional::get
)
))
.values()
);
lastUSDByDate.sort(Comparator.comparing(Currency::getLastReceived));
通過使用視窗函式構建本機 SQL 查詢以獲取每個日期的最新值,可以實作類似的結果。JPA 似乎還不支持視窗函式。
一個 PostgreSQL 的例子
// some JPA CurrencyRepository
@Query(nativeQuery = true, value = """
SELECT id, name, last_received
FROM (
SELECT c.*,
ROW_NUMBER() OVER (
PARTITION BY name, to_char(last_received, 'yyyy-MM-dd')
ORDER BY last_received DESC
) AS rr
FROM Currency c
WHERE c.name = :currName
) tbl
WHERE rr = 1
ORDER BY last_received
""")
List<Currency> findLastByDateByCurrencyName(@Param("currName") currName);
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/534493.html
