Как java Программа для проверки, если массив содержит заданные два разных значения? - PullRequest
1 голос
/ 17 января 2020

Я хочу написать код для проверки наличия двух указанных значений в списке.

List<Tag> tags = new ArrayList<>();

Требуется возвращать true только в том случае, если список tag содержит значения "start" и "end". Мой код такой, но он не отвечает требованиям.

public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
        boolean isSuccess = false;
        int count = 0;
        for (Tag tag : tags) {
            if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
                count++;
                if (count == 2)
                    break;
                isSuccess = true;
            }

        }
        return isSuccess;

Может ли кто-нибудь помочь мне решить эту проблему?

Ответы [ 4 ]

3 голосов
/ 17 января 2020

Это ...

if (count == 2)
  break;
isSuccess = true;

не имеет смысла. Это установит isSuccess, даже если есть только одно совпадение

Долгосрочный подход

Хорошо, давайте на секунду предположим, что вас волнует только один хотя бы один start и один end (без учета дубликатов). Один из подходов заключается в использовании флагов состояния: один для start и один для end. Чтобы было проще, они начинались бы с 0, но были бы максимумом 1 (потому что нам не нужны дубликаты), тогда вы могли бы сделать что-то вроде ...

public static boolean checkStartAndEndTimeTag(List<Tag> tags) {
    boolean isSuccess = false;
    int starts = 0;
    int ends = 0;
    for (Tag tag : tags) {
        if (tag.getKey().equals("start")) {
            starts = 1;
        } else if (tag.getKey().equals("end")) {
            ends = 1;
        }
    }
    isSuccess = (starts + ends) == 2;
    return isSuccess;
}

Хорошо, вам не нужно isSuccess = (starts + ends) == 2;, и вы можете просто return результат сравнения. Вы также можете выйти из l oop, если (starts + ends) == 2, и уберечь себя от ненужных вычислений

for (Tag tag : tags) {
    if (tag.getKey().equals("start")) {
        starts = 1;
    } else if (tag.getKey().equals("end")) {
        ends = 1;
    }

    if ((starts + ends) == 2) {
        break;
    }
}

Использование потоков ...

Одним из подходов может быть использование потоков поддержка и просто filter List и count результаты, например ...

import java.util.ArrayList;
import java.util.List;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        List<Tag> tags = new ArrayList<Tag>(25);
        tags.add(new Tag("begin"));
        tags.add(new Tag("front"));
        tags.add(new Tag("start"));
        tags.add(new Tag("finish"));
        tags.add(new Tag("tail"));
        tags.add(new Tag("end"));

        boolean isSuccessful = tags.stream().filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end")).count() >= 2;
        System.out.println(isSuccessful);
    }

    public class Tag {
        private String key;

        public Tag(String key) {
            this.key = key;
        }

        public String getKey() {
            return key;
        }


    }
}

Обновлено ...

Хорошо, это быстро усложнилось. Предположим, вы не хотите совпадать с двумя тегами start, поэтому вы ДОЛЖНЫ иметь оба тега end и один тег start

. Таким образом, используя приведенный выше пример, мы можем изменить Tag класс для поддержки equals (и с расширением hashcode)

public class Tag {

    private String key;

    public Tag(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    @Override
    public String toString() {
        return getKey();
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 73 * hash + Objects.hashCode(this.key);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Tag other = (Tag) obj;
        if (!Objects.equals(this.key, other.key)) {
            return false;
        }
        return true;
    }

}

Тогда мы можем просто использовать distinct, чтобы отфильтровать любые дубликаты, например ...

boolean isSuccessful = tags
        .stream()
        .distinct()
        .filter(tag -> tag.getKey().equals("start") || tag.getKey().equals("end"))
        .count() >= 2;

Вероятно, не самое эффективное решение, но, безусловно, одно из самых коротких

2 голосов
/ 17 января 2020

Вы также можете использовать

tags.stream()
    .map(Tag::getKey)
    .distinct()
    .filter(t -> "start".equals(t) || "end".equals(t))
    .count() == 2;

Это также решит проблему, из-за которой ваш исходный код неверно возвращает true, если список содержит statt или end дважды.

2 голосов
/ 17 января 2020

В этом коде

if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
     count++;
     if (count == 2)
            break;
     isSuccess = true;
}

вы устанавливаете isSuccess в значение true, когда tag равно start или end.

Лучшим способом будет

if (tag.getKey().equals("start") || tag.getKey().equals("end")) {
    count++;
    if (count == 2)
        return true;
}
0 голосов
/ 17 января 2020

А как же

tags.containsAll(Arrays.asList(new Tag("start"), new Tag("stop")))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...