我有一個objectIds 串列和一個<id,object> 映射。我需要檢查我的 objId 串列,并且對于每個 - 如果它在地圖中,將其添加到新的物件串列中,如果它不在串列中,則將 id 添加到缺少的 id 串列中。
我可以使用一個簡單的 for each 回圈輕松地做到這一點:
List<String> myIdList = Arrays.asList("a", "b", "c");
Map<String,Object> myObjectMap = new HashMap<>();
List<Object> objectList = new ArrayList<>();
List<String> missingObjIds = new ArrayList<>();
for(String id : myIdList) {
Object obj = myObjectMap.get(id);
if(obj == null) {
missingObjIds.add(id);
} else {
objectList.add(obj);
}
}
我想使用 Stream API 以一種不那么冗長的方式執行此操作,但我不確定如何。我嘗試對流進行磁區,但這讓我得到了一個帶有 2 個 id 串列的映射(這將需要再次通過串列來檢索映射的物件)或一個物件串列,其中所有丟失的物件都為空且無法獲取失蹤的身份證。
我確信必須有辦法做到這一點。有任何想法嗎?
uj5u.com熱心網友回復:
這不是很有效,但你可以做到。
List<String> myIdList = Arrays.asList("a", "b", "c");
Map<String,Object> myObjectMap = new HashMap<>();
myObjectMap.put("b", "B");
Map<Boolean, List<String>> partitioned = myIdList.stream()
.collect(Collectors.partitioningBy(myObjectMap::containsKey));
List<Object> objectList = partitioned.get(true).stream()
.map(myObjectMap::get).collect(Collectors.toList());
List<String> missingObjIds = partitioned.get(false);
System.out.println("objectList=" objectList);
System.out.println("missingObjIds=" missingObjIds);
輸出:
objectList=[B]
missingObjIds=[a, c]
uj5u.com熱心網友回復:
如果你真的想在這里使用流是一種方法。
- 這會根據 id 的存在創建一個條目。
- 然后它通過鍵“Missing”和“Present”對這些獨立條目進行分組
資料
List<String> myIdList = Arrays.asList("a", "b", "c");
Map<String, Object> myObjectMap = new HashMap<>();
myObjectMap.put("c", "C");
程序
Map<String, List<Object>> map = myIdList.stream()
.<Entry<String, Object>>mapMulti((id, consumer) -> {
Entry<String, Object> entry;
Object obj = myObjectMap.get(id);
if (obj == null) {
entry = new SimpleEntry<>("Missing", id);
} else {
entry = new SimpleEntry<>("Present", obj);
}
consumer.accept(entry);
}).collect(Collectors.groupingBy(Entry::getKey, Collectors
.mapping(Entry::getValue, Collectors.toList())));
System.out.println(map.get("Present"));
System.out.println(map.get("Missing"));
印刷
[C]
[a, b]
但我會堅持你所擁有的。這是有道理且有效的。
uj5u.com熱心網友回復:
這個邏輯可以在單個流陳述句中實作,并且沒有副作用,可以使用custom Collector
,也可以使用. 我會選擇后一種選擇。collect()
注意:我會但不會聲稱此解決方案不那么冗長。但它絕對是高性能和可維護的,并且客戶端代碼簡潔。
為此,我們需要定義一個自定義累積型別,它應該由一個能夠使用流元素并產生最終結果的可變物件表示。
由于我們需要獲取兩個不同的串列,因此流執行的結果應該是累加型別本身暴露這兩個串列。
因此,簡而言之,自定義型別,我們稱之為它Partitioner
,我們將使用它來執行可變歸約,它應該包含兩個串列。如果我們將其設為通用并添加一個Function
and Predicate
,它將更加通用,這將涉及將資料磁區到其屬性。
為了方便,我們可以實作Consumer
介面。
這就是流的實作方式:
public static void main(String[] args) {
List<String> myIdList = Arrays.asList("a", "b", "c");
Map<String, Object> myObjectMap = Map.of("a", "Alice");
Partitioner<String, Object> result = myIdList.stream()
.collect(
() -> new Partitioner<>(myObjectMap::containsKey, myObjectMap::get),
Partitioner::accept,
Partitioner::merge
);
System.out.println(result.getItems());
System.out.println(result.getKeys());
}
輸出:
[Alice] // Values assated with the Keys that match the IDs from the list
[b, c] // missing IDs
這就是自定義累積型別的樣子:
public class Partitioner<K, R> implements Consumer<K> {
private List<R> items = new ArrayList<>(); // objectList
private List<K> keys = new ArrayList<>(); // missingObjIds
private Predicate<K> shouldStoreItem;
private Function<K, R> mapper;
public Partitioner(Predicate<K> shouldStoreItem, Function<K, R> mapper) {
this.shouldStoreItem = shouldStoreItem;
this.mapper = mapper;
}
@Override
public void accept(K k) {
if (shouldStoreItem.test(k)) items.add(mapper.apply(k));
else keys.add(k);
}
public void merge(Partitioner<K, R> other) {
items.addAll(other.items);
keys.addAll(other.keys);
}
// getters
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/522322.html
標籤:爪哇java流
上一篇:我如何不使用math.sqrt來檢查數字是否是完美的平方
下一篇:使用擴展型別實作泛型方法