Я пытаюсь использовать потоки для перебора двух списков списков, чтобы проверить, совпадают ли размеры внутренних списков для одного и того же индекса. Мне удалось добиться этого с помощью потоков, но мне пришлось переписать, используя IntStream и mapToObj.

Мой текущий подход:

List<List<String>> a = config.getStrips();
List<List<Integer>> b = slotMachineConfig.getWeights();

a.stream()
 .filter(first ->
    b.stream()
     .allMatch(second -> second.size() == first.size())
 )
 .findFirst()
 .orElseThrow(InvalidConfigException::new);

Проблема в том, что я не могу быть уверен, что размеры будут соответствовать для больших списков, поэтому мне пришлось переписать это, используя IntStream, а также используя индексы для каждого списка.

То, что у меня есть до сих пор, но не работает, выглядит так: я пытаюсь написать функцию «проверки», чтобы проверить внутренние списки, но похоже, что я получаю сообщение об ошибке: «не существует экземпляра переменной типа U так что void соответствует U ".

IntStream.range(0, a.size())
    .mapToObj(i -> validate(i, a.get(i), b.get(i)))
    .findFirst()
    .orElseThrow(SlotMachineInvalidConfigException::new);

public void validate(int index, List<String> firstList, List<Integer> secondList) {

Как я могу переписать свой метод, используя IntStream и mapToObj, может ли кто-нибудь мне помочь?

0
Maria1995 15 Окт 2021 в 00:57

4 ответа

Лучший ответ

У вас есть правильная идея, но вам действительно не нужна отдельная функция проверки, если вы просто сравниваете размеры. Вот рабочий пример, который поддерживает любые типы списков:

public class ListSizeMatcher {
    public <T,S> boolean  sizeMatches(List<List<T>> list1, List<List<S>> list2) {
        return list1.size() == list2.size()
                && IntStream.range(0, list1.size())
                    .allMatch(i -> list1.get(i).size() == list2.get(i).size());
    }
    public static void main(String[] args) {
        ListSizeMatcher matcher = new ListSizeMatcher();
        System.out.println(matcher.sizeMatches(List.of(List.of(1)), List.of(List.of("a"), List.of("b"))));
        System.out.println(matcher.sizeMatches(List.of(List.of(1)), List.of(List.of("a", "b"))));
        System.out.println(matcher.sizeMatches(List.of(List.of(1, 2)), List.of(List.of("a", "b"))));
    }
}

Обратите внимание, что с точки зрения дизайна, если каждый элемент в списке соответствует соответствующему элементу в отдельном списке, вам лучше создать один класс, содержащий оба элемента.

1
sprinter 14 Окт 2021 в 23:15

Если я правильно понимаю, думаю, что-то вроде этого сработает:

List<List<String>> a = config.getStrips();
List<List<Integer>> b = slotMachineConfig.getWeights();

if (a.size() != b.size()) throw new InvalidConfigException();
boolean allTheSame = IntStream.range(0, a.size())
    .map(i -> a.get(i).size() - b.get(i).size())
    .allMatch(diff -> diff == 0);
if (!allTheSame) throw new InvalidConfigException();
1
David Conrad 14 Окт 2021 в 22:50

Для записи ваша функция проверки возвращает void, но я предполагаю, что она должна была возвращать логическое значение

Вот более компактная версия

               List<List<String>> a = new LinkedList<>();
        List<List<Integer>> b = new LinkedList<>();
        boolean match = IntStream.range(0, a.size())
                .mapToObj(i -> a.get(i).size() == b.get(i).size())
                .reduce(Boolean::logicalAnd).orElseThrow(InvalidConfigException::new);
        if (!match) {
            throw new InvalidConfigException();
        }

Альтернатива:

     List<List<String>> a = new LinkedList<>();
        List<List<Integer>> b = new LinkedList<>();
        if (IntStream.range(0, a.size()).filter(i -> a.get(i).size() != b.get(i).size()).count() > 0){
            throw new InvalidConfigException();
        };

В конце концов, достаточно одного, чтобы отличиться и потерпеть неудачу.

1
Christian Bongiorno 14 Окт 2021 в 23:23

Ошибка означает, что метод validate не может быть недействительным и ожидается, что он вернет некоторое допустимое значение (возможно, логическое).

Если предполагается, что внутренние списки имеют одинаковые размеры, чтобы быть действительными, проверка может выглядеть следующим образом:

// assuming the sizes of outer lists are equal
boolean allSizesEqual = IntStream.range(0, a.size())
    .allMatch(i -> a.get(i).size() == b.get(i).size());
if (!allSizesEqual) {
    throw new InvalidConfigException("Not all sizes are valid");
}

Если необходимо найти конкретные индексы, по которым обнаружено несоответствие:

List<Integer> badIndexes = IntStream.range(0, a.size())
    .filter(i -> a.get(i).size() != b.get(i).size()) // IntStream
    .boxed() // Stream<Integer>
    .collect(Collectors.toList());

if (!badIndexes.isEmpty()) {
    throw new InvalidConfigException("Different indexes found: " + badIndexes);
}

Или метод validate можно исправить так, чтобы он возвращал соответствующее значение для фильтра:

boolean allItemsValid = IntStream.range(0, a.size())
    .allMatch(i -> listsAreValid(a.get(i), b.get(i)));
if (!allItemsValid) {
    throw new InvalidConfigException("Not all entries are valid");
}

public boolean listsAreValid(List<String> innerA, List<Integer> innerB) {
// any advanced logic
    return innerA.size() == innerB.size();
}
1
Alex Rudenko 14 Окт 2021 в 23:31