我有一個具有 3 個屬性的類:
private static class OrderListItem {
public int price;
public int size;
public Type type;
}
此類的專案被添加到串列中。List<OrderListItem> orders_book = new ArrayList<>();
我想在串列中找到一個指定價格的物件。但大小和型別并不重要。我可以做這樣的事情:
int index = orders_book.indexOf(new OrderListItem(price, **any size**, **any type**));?
或者我必須做一個“回圈”搜索?
uj5u.com熱心網友回復:
我提供這個答案是一種可能性,盡管它可能超出您的實際要求。使用一些預定義的謂詞,它允許在串列中回傳任意數量的匹配的連續專案。如果沒有找到匹配項,將回傳一個空串列。
但首先,如果你想要索引(也許是物件的值),你可以這樣做,而不需要修改你的類。
- 這使用 an
IntStream流式傳輸所有可能的索引。 - 它將索引和該索引處的物件映射到
Map.entry - 然后它使用 的 過濾
value所需entry的屬性。 - 并回傳遇到的第一個或帶有 -1 和 null 的條目。(
AbstractMap.SimpleEntry此處用于允許空值)
int desiredPrice = 3;
Entry<Integer, OrderListItem> result = IntStream
.range(0, orderList.size())
.mapToObj(i -> Map.entry(i, orderList.get(i)))
.filter(e -> e.getValue().getPrice() == desiredPrice)
.findFirst().orElse(new AbstractMap.SimpleEntry<>(-1,null));
為了便于演示,record使用以下代替類定義。一個類可以直接替換它。還提供了一個型別列舉。
enum Type {
FICTION, TECHNICAL, BIOGRAPHY
}
private record OrderListItem(int getPrice, int getSize,
Type getType) {
@Override
public String toString() {
return String.format("[%s, %s, %s]", getPrice, getSize,
getType);
}
}
現在定義一些謂詞。每個都需要一個orderListItem物件和一個Type. 比較方法(等于或 ==)取決于屬性型別。該謂詞和所需的屬性值將提供給稍后顯示的方法。即使您只對 感興趣price,其他人也很容易添加。
static BiPredicate<OrderListItem, Integer> CHECK_PRICE =
(order, val) -> order.getPrice() == val;
static BiPredicate<OrderListItem, Type> CHECK_TYPE =
(order, val) -> order.getType().equals(val);
static BiPredicate<OrderListItem, Integer> CHECK_SIZE =
(order, val) -> order.getSize() == val;
一些資料
List<OrderListItem> orderList =
ArrayList<>(List.of(new OrderListItem(3, 20, Type.FICTION),
new OrderListItem(4, 20, Type.TECHNICAL),
new OrderListItem(5, 20, Type.TECHNICAL),
new OrderListItem(3, 30, Type.FICTION),
new OrderListItem(4, 30, Type.FICTION),
new OrderListItem(5, 30, Type.TECHNICAL),
new OrderListItem(3, 40, Type.FICTION),
new OrderListItem(4, 40, Type.BIOGRAPHY),
new OrderListItem(5, 40, Type.FICTION),
new OrderListItem(3, 50, Type.FICTION),
new OrderListItem(4, 50, Type.BIOGRAPHY),
new OrderListItem(5, 50, Type.BIOGRAPHY)));
演示
List<OrderListItem> matches =
retrieve(orderList, CHECK_SIZE, 20, 2);
matches.forEach(System.out::println);
印刷
[3, 20, FICTION]
[4, 20, TECHNICAL]
該方法采用以下引數。
- 訂單清單
- 比較謂詞
- 要比較的屬性值
- 成功匹配的期望回傳計數(負值將導致回傳所有匹配)。
該方法通過對訂單進行簡單的迭代來作業,將謂詞應用于訂單和屬性。如果找到匹配項,則將其添加到回傳串列并減少計數。當計數達到0或檢查整個串列時,將回傳串列。
public static <T> List<OrderListItem> retrieve(
List<OrderListItem> orders,
BiPredicate<OrderListItem, T> pred, T attribute,
int count) {
List<OrderListItem> matches = new ArrayList<>();
for (OrderListItem order : orders) {
if (pred.test(order, attribute)) {
matches.add(order);
if (--count == 0) {
break;
}
}
}
return matches;
}
表現
與 JMH 相比,這不是最好的測驗,而是一個粗略的想法。
- 首先,我將資料串列添加到自身 20 次以創建一個大串列。
- 我對所有記錄重復上述查找,但沒有列印輸出。
for (int i = 0; i < 20; i ) {
orderList.addAll(orderList);
}
System.out.printf("%,d total objects%n",orderList.size());
long time = System.nanoTime();
List<OrderListItem> matches =
retrieve(orderList, CHECK_SIZE, 20, -1);
System.out.println("Execution time ~ " (System.nanoTime()-time)/1e9 " sec");
印刷
12,582,912 total objects
Execution time ~ 0.632698253 sec
沒有為整個串列找到匹配項,結果是
Execution time ~ 0.033943752 sec.
為了匹配整個串列,結果是
Execution time ~ 0.939900075 sec.
時間差異主要是由于(imo)隨著容量的增加必須更新后備陣列。這需要對陣列進行多次重新復制。通過將回傳串列的初始容量設定為orders.size(),提高了匹配和回傳所有元素的結果。
為了將整個串列與調整后的容量匹配,結果是Execution time ~ 0.19100866 sec
我在 Intel 4 核 I7 處理器上運行 Windows。
我不知道以上任何一項與您的要求有何關系,但它是為了您的啟迪。
uj5u.com熱心網友回復:
如果您需要檢索具有所需價格的實體,則可以使用帶有filterandfindAny操作的集合流。
int myPrice = /* any value you want */
//This will retrieve an instance with the disired price or null if none is found
OrderListItem item = orders_book.stream()
.filter(i -> i.getPrice() == myPrice)
.findFirst()
.orElse(null);
或者,如果您想檢索具有所需價格的物件的索引,那么您有兩種選擇:
- 重新定義
equals您的OrderListItem類的方法,使其價格等于兩個 OrderListItem,因為該方法的檔案indexOf通過其方法檢索元素equals。但是,我不會傾向于這種解決方案,因為在我看來,唯一的價格不足以等于兩個訂單專案,但你肯定比我更了解你正在建模的問題型別。所以,我會把選擇權留給你。此外,如果您重新定義該equals方法,您還應該將該hashCode方法重新定義為通用哈希碼合約狀態。
https://docs.oracle.com/javase/8/docs/api/java/util/List.html#indexOf-java.lang.Object-
回傳此串列中指定元素第一次出現的索引,如果此串列不包含該元素,則回傳 -1。更正式地說,回傳滿足 (o==null ? get(i)==null : o.equals(get(i))) 的最低索引 i,如果沒有這樣的索引,則回傳 -1。
class OrderListItem {
public int price;
public int size;
public Type type;
/* ... your implementation ...*/
@Override
public int hashCode() {
return Objects.hash(price);
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (this == obj) return true;
if (getClass() != obj.getClass()) return false;
OrderListItem other = (OrderListItem) obj;
return Objects.equals(price, other.price);
}
}
- 不是重新定義 equals 方法,而是使用流檢索確切的實體(如在第一個片段中),然后使用相同的實體作為
indexOf呼叫的引數。
int myPrice = /* any value you want */
//This will retrieve an instance with the disired price or null if none is found
OrderListItem item = orders_book.stream()
.filter(i -> i.getPrice() == myPrice)
.findFirst()
.orElse(null);
//Retrieving the index
int index = orders_book.indexOf(item);
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/476414.html
上一篇:Julia中似然的有效網格近似
