#java #java-stream
Вопрос:
Я пытаюсь использовать потоки для перебора двух списков списков, чтобы проверить, одинаковы ли размеры внутренних списков для одного и того же индекса. Мне удалось добиться этого с помощью потоков, но я должен переписать, используя 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
, может ли кто-нибудь мне помочь?
Комментарии:
1.
validate()
это пустой метод. Вы не можете использовать его какFunction
.
Ответ №1:
У вас есть правильная идея, но на самом деле вам не нужна отдельная функция проверки, если вы просто сравниваете размеры. Вот рабочий пример, который поддерживает любые типы списков:
public class ListSizeMatcher {
public <T,S> boolean sizeMatches(List<List<T>> list1, List<List<S>> list2) {
return list1.size() == list2.size()
amp;amp; 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"))));
}
}
Обратите внимание, что с точки зрения дизайна, если каждый элемент в списке соответствует соответствующему элементу в отдельном списке, вам лучше создать один класс, содержащий оба элемента.
Ответ №2:
Если я правильно понимаю, я думаю, что что-то подобное сработает:
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();
Ответ №3:
Для записи, ваша функция проверки возвращает 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, чтобы быть другим и потерпеть неудачу.
Ответ №4:
Ошибка означает, что 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();
}