2

We have two lists one is of type Question and the other of type Tag.

The Question class has those attributes

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

The Question list has several questions in it and the Tag list has all tags in it. We wanna check if One question contains any tag of the tag list. I want to do this for all questions.

With question.getTags, I get the list of tags.

I tried

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
        }
    }
}

This is not quite doing what I want to do, I think I have to do something with streams but I could not quite figure out how I exactly have to write the code.

yassoplaya
  • 67
  • 1
  • 3
  • 9

5 Answers5

1

You're performing the operation for every tag that's in the list instead of once per question if any tag is in the list.

As you proposed, using streams could make this solution easier:

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

Note - this still has an O(m * n) runtime complexity, where m is the number of questions and n is the number of tags. You can optimize this to an O(m + n) runtime complexity by creating a Set from the list of tags so that the contains operation has an O(1) time complexity.

Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • This could be good, one more thing when it matches how I could add that that tag which matches to a list for example – yassoplaya Jun 18 '20 at 18:04
1

Apache commons have an utility method for that: CollectionUtils#containsAny

krzychek
  • 300
  • 3
  • 9
0
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
    }
}
kaweesha
  • 803
  • 6
  • 16
0

To get all tags that contain in alltags list and their occurrence map

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

Then you can add this list in another list if you want. And recomend you to make a set for alltags then it will faster since allTagsSet.contains takes O(1) only.

Eklavya
  • 17,618
  • 4
  • 28
  • 57
-1

Try:

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

Or are you asking whether the a given question contains a token from the question.tags() list?

Rob Evans
  • 2,822
  • 1
  • 9
  • 15
  • How is that different than the loop in the question, except that `Question` probably doesn't have a `contains` method? – daniu Jun 18 '20 at 15:37