[英]Java filter List that so it only contains objects that have same attribute as in another lists
我有兩個包含幾個對象的列表。 我想過濾在特定屬性包含相同String值的對象。 所以我們假設listA
包含具有屬性id
對象。 對於listB
,盡管它包含不同的對象。 兩個列表中的某些對象具有相同的ID。 我想過濾這些對象並將它們放在一個新列表中。 這是我到目前為止所得到的:
List<Customer> Clist = Customer.getAllCustomers();
List<License> Llist = License.getAllLicenses();
Predicate<Customer> customerNotNullPredicate = u -> (u.id != null);
Predicate<License> licenseNotNullPredicate = u -> (u.id != null);
List<Customer> Clistfiltered1 = Clist.parallelStream().filter(customerNotNullPredicate).collect(Collectors.toList());
List<License> Llistfiltered1 = Llist.parallelStream().filter(licenseNotNullPredicate).collect(Collectors.toList());
Clistfiltered1.retainAll(Llistfiltered1);
try {
Clistfiltered1.get(0);
} catch (Exception e){
System.out.println(e);
}
如果是course, retainAll()
不會返回任何內容,因為兩個列表只包含不同類型的對象。 我如何嘗試對對象的特定屬性使用retainAll()
?
非常感謝你提前。
您的任務描述不明確,但顯然,您希望獲得所有Customer
實例,其中存在具有相同id
的License
實例。
雖然可以將其描述為一個流操作,但是在一個列表中為另一個列表的每個元素搜索匹配將意味着O(nxm)
時間復雜度的操作,換句話說,如果你有,它將表現得非常糟糕大名單。
因此,最好在具有O(n+m)
時間復雜度的兩個操作中執行此操作:
List<Customer> cList = Customer.getAllCustomers();
List<License> lList = License.getAllLicenses();
Set<?> licenseIDs = lList.stream()
.map(l -> l.id).filter(Objects::nonNull)
.collect(Collectors.toSet());
List<Customer> cListFiltered = cList.stream()
.filter(c -> licenseIDs.contains(c.id))
.collect(Collectors.toList());
if(cListFiltered.isEmpty()) System.out.println("no matches");
else cListFiltered.forEach(System.out::println);
雖然未指定collect(Collectors.toSet())
返回的確切Set
類型,但您可以預期它具有優於線性查找,這允許在后續流操作中使用其contains
方法。 請注意,只有第一個操作具有null
值的過濾器; 因為這可以保證licenseIDs
集不包含null
,所以具有null
id的客戶將被隱式拒絕。
很容易獲得常見的ID
Set<?> commonIDs = cList.stream()
.map(l -> l.id).filter(licenseIDs::contains)
.collect(Collectors.toSet());
如果您commonIDs
,可以使用commonIDs
,同時過濾客戶列表或許可證列表。
您不能在兩種不同類型(客戶和許可證)之間執行retainAll操作。 我建議你只找到兩個集合中的id,然后根據需要使用它們
List<Long> customerIds = Clist.map(Customer::id).filter(Objects::notNull);
List<Long> licenseIds = Llist.map(Customer::id).filter(Objects::notNull);
List<Long> sharedIds = cusomerIds
.stream()
.filter(customerId -> licenseIds.contains(customerId))
.collect(Collectors.toList());
顯然,不確定你的案例中的id是否為Long,但它應該適用於所有類型。
在這種情況下你不能使用retainAll(),但我會解決這個問題:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DifferentCollections {
public static void main(String[] args) {
List<Customer> customers = new ArrayList<>(Arrays.asList(new Customer(1), new Customer(2), new Customer(10)));
List<License> licenses = new ArrayList<>(Arrays.asList(new License(1), new License(2), new License(30)));
List<Customer> filteredCustomers = customers.stream().
filter(c -> customerIdFoundInLicensesList(c, licenses)).
collect(Collectors.toList());
System.out.println(filteredCustomers);
}
private static boolean customerIdFoundInLicensesList(Customer customer, List<License> licenses) {
return licenses.stream().
filter(l -> l.getId().equals(customer.getId())).
findAny().
isPresent();
}
}
class Customer {
Integer id;
public Customer(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "Customer{" + "id=" + id + '}';
}
}
class License {
Integer id;
public License(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
@Override
public String toString() {
return "License{" + "id=" + id + '}';
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.