如何等于3 ArrayList <string>并检查此列表中对象的匹配?

时间:2016-07-27 08:40:11

标签: java list arraylist collections

我有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;

如果更容易

3 个答案:

答案 0 :(得分:2)

我认为您已经找到了一个可接受的答案,即将三个列表添加到集合中。这是一个等效且更通用的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();
    }
}

答案 1 :(得分:1)

使用三组而不是列表。这有几个好处:

  • 由于每个集合不应包含重复元素,因此使用Set(不允许此类重复元素共存)更加清晰,可以避免潜在的错误。
  • 设置操作(add,contains,...)比列表操作更有效。特别是,在列表中查找元素是O(|列表|的大小),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());

答案 2 :(得分:0)

效率和优雅的良好结合可能是:

.st

或更有用:

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

告诉你哪个项目是重复的。

一旦找到第一个副本,两个版本的代码都会抛出异常。