Iterate over two Lists of Lists with IntStream instead of streams

I am trying to use streams in order to iterate over two lists of lists in order to verify if the inner lists sizes are the same for the same index. I have managed to achieve this using streams, but I have to rewrite using an IntStream and mapToObj.

My current approach is:

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);

The problem is that I cannot be sure that the sizes will correspond for the big lists, so I have to rewrite this using IntStream and also using indexes for each list.

What I have so far, but does not work looks like this, I am trying to write a “validate” function in order to verify the inner lists, but it seems like I get an error there saying “no instance of type variable U exist so that void conforms to 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) {

How can I rewrite my method using IntStream and mapToObj, can anyone help me?

Answer

You have the right idea but you don’t really need a separate validation function if you are just comparing sizes. Here’s a working example that supports any list types:

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"))));
    }
}

Note that from a design perspective if each item in the list matches the corresponding item in a separate list you’d be better off creating a single class that contains both items.