簡體   English   中英

Java過濾器列表,它只包含與另一個列表中具有相同屬性的對象

[英]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實例,其中存在具有相同idLicense實例。

雖然可以將其描述為一個流操作,但是在一個列表中為另一個列表的每個元素搜索匹配將意味着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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM