簡體   English   中英

如何等於3 ArrayList <String> 並檢查此列表中對象的匹配項?

[英]How equals 3 ArrayList<String> and check matches of objects in this lists?

我有3個字符串列表

private @Getter @Setter List<String> allowedServicesId;
private @Getter @Setter List<String> notAllowedServicesId;
private @Getter @Setter List<String> replaceServiceId;

並且我需要檢查這些列表中是否至少有一個對象的交集?

我創建了這個

        for (String s : allowedServicesId) {
            if (notAllowedServicesId.contains(s)){
                throw new Exception("");
            }
            if (replaceServiceId.contains(s)){
                throw new Exception("");
            }
        }
        for (String s : notAllowedServicesId) {
            if (replaceServiceId.contains(s)){
                throw new Exception("");
            }
        }

但是我認為這是不好的做法。 我認為還有另一種方式。

編輯

我想到了

Set<String> set = new HashSet<>();
        set.addAll(allowedServicesId);
        set.addAll(notAllowedServicesId);
        set.addAll(replaceServiceId);
        int i = allowedServicesId.size() + notAllowedServicesId.size() + replaceServiceId.size();
        if (set.size()!= i){
            throw new Exception("");
        }

跟你一樣

編輯

我可以將List更改為Set

private @Getter @Setter Set<String> allowedServicesId;
private @Getter @Setter Set<String> notAllowedServicesId;
private @Getter @Setter Set<String> replaceServiceId;

如果更容易

我認為您已經找到了將三個列表添加到集合中的想法。 這是一個等效的通用Java 8代碼

private static void assertForDuplicates(Collection<?>... collections) throws Exception {
    int n = 0;
    for (Collection<?> c : collections) {
        n += c.size();
    }

    if (Stream.of(collections).flatMap(Collection::stream).collect(Collectors.toSet()).size() != n) {
        throw new Exception();
    }
}

使用三組而不是列表。 這有幾個優點:

  • 由於每個集合都不應該包含重復元素,因此使用Set (不允許這樣的重復元素共存)既更清楚,又可以避免潛在的錯誤。
  • 設置操作(添加,包含,...)比列表操作效率更高。 特別是,在列表中查找元素是O(| list | size)和HashSet O(1)。

假設您正在使用集合,則以下代碼是測試String集合中重復項的有效方法:

private boolean hasDuplicates(Set<String> ... sets) {
    if (sets.size() < 2) return false; // no possible duplicates
    Set<String> all = Hashnew Set<>();
    for (Set<String> set : sets) {
        for (String s : set) {
            // adding to a set returns false if element was already there
            if ( ! all.add(s)) return true;
        }
    }
    return false;
}

一旦找到第一個重復項,此操作就會失敗(並且可以輕松修改以報告匹配發生的位置)。 在最壞的情況下,這等效於您的代碼,其中添加了所有元素,然后進行測試以查看總大小是否符合預期。


編輯-另類

您似乎正在使用多個哈希集來保留服務的專有布爾屬性。 考慮改用創建Service類:

public class Service {

    public enum Status { ALLOWED, REPLACE, NOT_ALLOWED };

    private String id;
    private Status status;

    // constructors, getters & setters here

    public int hashCode () { return id.hashCode(); }
    public boolean equals(Object o) { 
        return o instanceof Service && id.equals(((Service)o).getId()); 
    }        
}

這使您可以保留一個集合:

Set<Service> services; // guaranteed: each has exactly one status

更好的是,您將使用地圖按其ID有效地檢索服務:

Map<String, Service> servicesById; 

Service httpService = servicesById.get("http");
System.out.println("The status of service http is " + httpService.getStatus());

效率和優雅的完美結合可能是:

Set<String> set = new HashSet<>();
if (Stream.of(allowedServicesId, notAllowedServicesId, replaceServiceId)
        .flatMap(List::stream).anyMatch(s -> !set.add(s)))
    throw new Exception();

或更有用:

Optional<String> dupe = Stream.of(allowedServicesId, notAllowedServicesId, replaceServiceId)
        .flatMap(List::stream)
        .filter(s -> !set.add(s))
        .findFirst();
if (dupe.isPresent())
  throw new Exception(dupe + " was duplicated");

告訴您哪些項目已重復。

找到第一個重復項后,這兩個版本的代碼都將引發異常。

暫無
暫無

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

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