【问题标题】:Check if list contains any item of another list in java检查列表是否包含java中另一个列表的任何项目
【发布时间】:2020-06-18 14:58:55
【问题描述】:

我们有两个列表,一个是 Question 类型,另一个是 Tag 类型。

Question 类具有这些属性

private String id;
private String header;
private String content;
private List<Tag> tags;
private Long timeStamp;

问题列表中有几个问题,标签列表中有所有标签。 我们想检查一个问题是否包含标签列表的任何标签。 我想对所有问题都这样做。

使用question.getTags,我得到标签列表。

我试过了

List<Question> allQuestions =  ... ; // List of type questions
List<Tags> alltags = ... ;  // List of type tag

for(Question question: allQuestions) {
    for(Tag tag: allTags){
        if(question.getTags().contains(tag)) {
            //do something
        }
    }
}

这并不是我想做的事情,我想我必须对流做一些事情,但我无法弄清楚我究竟要如何编写代码。

【问题讨论】:

    标签: java list


    【解决方案1】:

    如果 any 标记在列表中,则您正在对列表中的 每个 标记执行操作,而不是每个问题一次。

    正如您所建议的,使用流可以使这个解决方案更容易:

    allQuestions.forEach(question -> {
        if (question.getTags().stream().anyMatch(tag -> allTags.contains(tag)) {
            // do something
        }
    });
    

    注意 - 这仍然具有 O(m * n) 的运行时复杂度,其中 m 是问题的数量,n 是标签的数量。您可以通过从标签列表中创建Set 将其优化为 O(m + n) 运行时复杂度,以便 contains 操作具有 O(1) 时间复杂度。

    【讨论】:

    • 这可能很好,当它匹配时,我可以添加与列表匹配的标签,例如
    【解决方案2】:

    Apache commons 有一个实用方法:CollectionUtils#containsAny

    【讨论】:

      【解决方案3】:
      List<Question> allQuestions =  ... ; // List of type questions
      List<Tags> alltags = ... ;  // List of type tag
      
      for (Question x : allQuestions) {
          List<Tag> questionTags = new ArrayList<>();
          questionTags = x.getTags();
          questionTags.retainAll(allTags);
          // questionTags will retain common tags between allTags and x.getTags()            
      
          for (Tag tag: questionTags) {
              // Execute when there is at least one common tag
          }
      }
      

      【讨论】:

        【解决方案4】:

        获取alltags列表中包含的所有标签及其出现图

        Map<Tag, Long> map = allQuestions.stream()
                                   .flatMap(q -> q.getTags().stream())
                                   .filter(t -> allTags.contains(t))
                                   .collect(Collectors.groupingBy(e -> e, Collectors.counting()));
        

        然后,您可以根据需要将此列表添加到另一个列表中。 并建议您为alltags 设置一个集合,因为allTagsSet.contains 只需要O(1),它会更快。

        【讨论】:

        • 现在您可以获得地图值中每个标签的出现次数
        • 它不是很有效,计数错误,有些标签甚至不在地图中
        • @yassopaya 你是否为 Tag 类定义 equals 和 hashcode ?如果没有,那么它就不能作为地图键。
        • 我不明白你的意思
        • 要了解为什么你需要做stackoverflow.com/questions/1894377/… 以及为什么它不起作用stackoverflow.com/questions/6871929/…
        【解决方案5】:

        试试:

        for(Question question: allQuestions) {
            for(Tag tag: allTags){
                if(question.contains(tag)) {
                    //do something
                }
            }
        }
        

        或者您是在询问给定问题是否包含 question.tags() 列表中的标记?

        【讨论】:

        • 除了Question 可能没有contains 方法之外,这与问题中的循环有何不同?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多