Как проверить, содержит ли объект одного списка объект другого списка - PullRequest
3 голосов
/ 19 июня 2020

У нас есть два списка: один относится к типу Question, а другой - к типу Tag.

Класс Question имеет эти атрибуты

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

Список вопросов содержит все вопросы и В списке тегов есть все теги. Мы хотим проверить, содержит ли один вопрос какой-либо тег из списка тегов. Я хочу сделать это для всех вопросов.

С помощью question.getTags я получаю список тегов.

Класс Tag имеет атрибут с именем counter.

Я буду дайте какой-нибудь псевдокод, чтобы на самом деле показать вам, что я хочу сделать

List<Tag> allTags = ...
List<Question> allQuestions = ...
Map<Tag,Integer> map = new Hashmap<>();

if(one question contains any tag of allTags) {
     tag.setCounter(counter+1);
     map.put(tag,tag.getCounter);
}

В конце концов, я хочу иметь карту, где ключ - это тег, а значение - счетчик этого тега. могу я это сделать?

EDIT вот мой тег. java

@NoArgsConstructor
@Data
@Getter
@AllArgsConstructor
@Setter
@Document(collection = "tag")
public class Tag {
    private String id;
    private String name;
    private Long timeStamp;

public Tag(String name) {
        this.id = UUID.randomUUID().toString();
        this.name = name;
        this.timeStamp = Instant.now().getEpochSecond()*1000;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Tag tag = (Tag) o;
        return Objects.equals(getId(), tag.getId());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getId());
    }
}

Ответы [ 2 ]

1 голос
/ 19 июня 2020

Я думаю, что атрибут счетчика в классе Tag для подсчета того, как часто Tag встречается в списке questions, является ошибкой дизайна. Там такой счетчик не нужен.

Возможный правдоподобный пример: представьте, что у вас есть класс Student и класс Course. Чтобы отслеживать, сколько студентов обучается на курсе, счетчик в классе Student не нужен. Таким же образом класс Tag должен содержать только атрибуты тега. Тем не менее, вы можете достичь своей цели без счетчика с помощью одного из двух следующих подходов (при условии, что у вас java 8 или выше и ваш класс Tag переопределяет методы equals и hashcode):

Подход 1 с использованием Streams & Collectors.groupingBy

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

Подход 2 с использованием List.forEach & Map.compute

Map<Tag, Integer> map2 = new HashMap<>();
    allQuestions.forEach(q -> {
        q.getTags()
                .stream()
                .filter(allTags::contains)
                .forEach(t -> map2.compute(t, (k, v) -> v == null ? 1 : v + 1));
    });

Или с использованием традиционных for-loop и if-else блок

Map<Tag, Integer> map3 = new HashMap<>();

for (Question q : allQuestions) {
    for (Tag t : q.getTags()) {
        if (allTags.contains(t)) {
            if (map3.containsKey(t)) {
                map3.put(t, map3.get(t) + 1);
            } else {
                map3.put(t, 1);
            }
        }
    }
}
0 голосов
/ 19 июня 2020

Думаю, сработает отлично

    int count=0; 
    for(Question q : allQuestions){
     for(Tag t : q.getTags()){
     if(allTags.contains(t)){ 
        count=map.containsKey(t) ? map.get(t)+1 : 0;
        map.put(t,count);
       }
     }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...