簡體   English   中英

有沒有一種通用的方法來獲取 Java 中兩個列表的交集?

[英]Is there a generic way to get the intersection of two lists in Java?

有沒有一種通用的方法來獲取 Java 中兩個列表的交集?

無論列表中的元素是 String、Long、Integer 還是 BigDecimal 類型,我都希望有一種方法可以找到 list1 和 list2 中包含的元素。

我試圖用下面的代碼來實現這一點,直到 arguments 都包含相同類型的元素,否則它在運行時返回一個空列表。

private <T> List<T> intersect(List<T> list1, List<T> list2) {
        
    List<T> list = new ArrayList<T>();
    
    System.out.println("list1= "+list1);
    System.out.println("list2= "+list2);
    for (T t2 : list2) {
        System.out.println("t2= "+t2 + ", class: " + t2.getClass());
    }
    
    for (T t : list1) {
        System.out.println("t= "+t + ", class: " + t.getClass());
        if(list2.contains(t)) {
            System.out.println("list2 containts t");
            list.add(t);
        }
    }
    System.out.println("list= "+list);
    return list;
}

調用 intersect 方法的代碼:

import javax.ws.rs.core.Response;

public boolean process(Response response, List<Object> sentObjects) {
String body = response.readEntity(String.class);
....
List<Object> parsedResponse = parseJson(body);
List<Object> intersection = intersect(sentObjects, parsedResponse);
...
}

列表中包含不同類型元素的示例 output:

list1= [11190, 11191, 11213]
list2= [11190, 11191, 11213]
t2= 11190, class: class java.lang.Long
t2= 11191, class: class java.lang.Long
t2= 11213, class: class java.lang.Long
t= 11190, class: class java.math.BigDecimal
t= 11191, class: class java.math.BigDecimal
t= 11213, class: class java.math.BigDecimal
list= []

問題:有什么方法可以強制 list1 的類型 T 與 list2 的類型 T 相同,而無需明確告知確切的類型?

您可以 select 一種通用類型,在檢查相等性之前可以將所有元素轉換為該類型。 Object.equals()方法依賴於實現,但對於不同類型的 object,它很少返回true ,尤其是在參數不是派生類型時。

在這種特殊情況下,似乎常見的類型可能是String 也就是說, LongIntegerBigDecimal都可以一致地轉換為字符串表示。

據推測,您正在使用的String對象是沒有分隔符的十進制數(對於千位等)。 如果是這種情況,您只需在數字類型上調用toString()即可創建等效表示。 否則,您可以使用適當配置的NumberFormat以匹配String元素的預期格式。

List<T> intersect(List<? extends T> t1, Collection<?> t2) {
    Set<String> tmp = t2.stream().map(Object::toString).collect(Collectors.toSet());
    return t1.stream()
        .filter(e -> tmp.contains(e.toString()))
        .collect(Collectors.toList());
}

Collection.contains的定義只允許使用相等來檢查元素; 不同類的實例通常不相等(例如,長零和 BigDecimal 零不相等;但是空的 ArrayList 和空的 LinkedList 是)。

為了解決這個問題,你需要使用比 equals 更通用的東西,比如BiPredicate<T, T>

if(list2.stream().anyMatch(u -> biPredicate.apply(t, u))) {

您需要將 BiPredicate 作為參數傳遞給您的方法,例如

BiPredicate<Number, Number> biPredicate = (t, u) -> t.longValue() == u.longValue();

也許您可以直接使用 Object class 。 如果您只是使用 Object class 的子類。 希望能幫助到你。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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