我有這樣的方法:
public String mostExpensiveItems() {
List<Entry> myList = getList();
List<Double> expensive = myList.stream()
.map(Entry::getAmount)
.sorted(Comparator.reverseOrder())
.limit(3)
.toList();
return "";
}
此方法需要以字串形式回傳 3 個最昂貴商品的產品 ID,如下所示:“item1, item2, item3”。我應該只能使用流,但我被困在這里。我應該能夠按價值對專案進行排序,然后獲取產品 ID,但我似乎無法讓它作業。
編輯:
產品 ID 位于 Entry 類中
public class Entry {
private String productId;
private LocalDate date;
private String state;
private String category;
private Double amount;
public Entry(LocalDate orderDate, String state, String productId, String category, Double sales) {
this.date = orderDate;
this.productId = productId;
this.state = state;
this.category = category;
this.amount = sales;
}
public String getProductId() {
return productId;
}
uj5u.com熱心網友回復:
假設產品 ID 在 Entry 中,它可能是這樣的。
public String mostExpensiveItems() {
List<Entry> myList = getList();
List<String> expensive = myList.stream()
.sorted(Comparator.comparing(Entry::getAmount).reversed())
.limit(3)
.map(Entry::getProductID)
.toList();
return "";
}
注意:我還沒有對此進行測驗,但這應該能夠傳達這個想法。
uj5u.com熱心網友回復:
您不必為此任務對所有給定資料進行排序。因為排序是多余的,所以只需要獲取3最大值。
因為對孔資料集進行排序將花費O(n log n)時間。同時,這個任務可以通過串列一次完成,只維護3排序順序中最大的先前遇到的值。而且時間復雜度會非常接近線性時間。
要使用流實作部分排序,您可以定義一個自定義收集器(一個負責從流中累積資料的物件)。
您可以通過使用其中一個靜態方法版本或通過創建實作介面的方法來行內創建自定義收集器。Collector.of()classCollector
這些是您在定義自定義收集器時需要提供的引數:
- 供應商
Supplier<A>旨在提供一個可變容器來存盤流的元素。在這種情況下,因為我們需要執行部分排序,PriorityQueue所以作為可變容器將很方便。 - 累加器BiConsumer<A,T> 定義如何將元素添加到供應商提供的容器中。對于此任務,累加器需要通過拒絕小于先前添加到佇列中的最小值的值來保證佇列不會超過給定大小,如果大小已達到限制,則洗掉最小值需要新值被添加。
- Combiner
BinaryOperator<A> combiner()建立了一個規則,關于如何合并并行執行流時獲得的兩個容器。這里組合器依賴于為累加器描述的相同邏輯。 - Finisher
Function<A,R>旨在通過轉換可變容器來產生最終結果。下面代碼中的 Finisher 函式將佇列變成了一個不可變的串列。 - 特性允許提供附加資訊,例如
Collector.Characteristics.UNORDERED,在這種情況下使用的特性表示并行執行時產生的部分縮減結果的順序并不重要,這可以提高此收集器在并行流中的性能。
請注意,Collector.of()只有供應商、累加器和組合器是強制性的,如果需要,還定義了其他引數。
通過應用泛型型別引數并提供比較器作為引數,可以使下面生成收集器的方法更加可重用。
自定義收集器:
public static Collector<Double, ?, List<Double>> getMaxN(int size) {
return Collector.of(
PriorityQueue::new,
(Queue<Double> queue, Double next) -> tryAdd(queue, next, size),
(Queue<Double> left, Queue<Double> right) -> {
right.forEach(next -> tryAdd(left, next, size));
return left;
},
(Queue<Double> queue) -> queue.stream().toList(),
Collector.Characteristics.UNORDERED);
}
public static void tryAdd(Queue<Double> queue, Double next, int size) {
if (queue.size() == size && queue.element() < next) queue.remove(); // if next value is greater than the smallest element in the queue and max size has been exceeded the smallest element needs to be removed from the queue
if (queue.size() < size) queue.add(next);
}
溪流:
public static List<Double> getMostExpensive(List<Entry> entries, int limit) {
return entries.stream().parallel()
.map(Entry::getAmount)
.collect(getMaxN(limit));
}
main()Entries- 帶有僅期望amount作為引數的假人的演示。
public static void main(String[] args) {
List<Entry> entries =
List.of(new Entry(2.6), new Entry(3.5), new Entry(5.7),
new Entry(1.9), new Entry(3.2), new Entry(9.5),
new Entry(7.2), new Entry(8.1), new Entry(7.9));
System.out.println(getMostExpensive(entries, 3));
}
輸出
[7.9, 9.5, 8.1] // final result is not sorted PriorityQueue maintains the elements in unsorted order (sorting happens only while dequeue operation happens), if these values are requeted to be sorted it could be done by changing the finisher function
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/467954.html
上一篇:批量運行時出現Repast錯誤,錯誤:InstanceRunner-運行模型時出錯
下一篇:該欄位不可見JAVA
