'How to make a new List of ArrayList from a List of ArrayList?

Another silly question from a complete beginner.

I have a List<ArrayList<Boolean>> isExpenseByMonth with the following contents:

[[true, true, true, false, false, false], [true, true, false, false, false], [true, true, true, false, false, false]].

I need to "convert" boolean values to integers (true = -1, false = 1) and place them to a new List<ArrayList<Integer>> boolToIntByMonth so that it'd look like this (ArrayList<Integer>s should be of the same size as ArrayList<Boolean>s):

[[-1, -1, -1, 1, 1, 1], [-1, -1, 1, 1, 1], [-1, -1, -1, 1, 1, 1]]

So far I've tried to play around with the following code:

ArrayList<Integer> boolToInt = new ArrayList<>();
//List<ArrayList<Integer>> boolToIntByMonth = new ArrayList<>();
        
for (ArrayList<Boolean> arr : isExpenseByMonth) {
    for (boolean b : arr) {
        if (b) {
            boolToInt.add(-1);
            //boolToIntByMonth.add(boolToInt);
        } else {
            boolToInt.add(1);
            //boolToIntByMonth.add(boolToInt);
        }
    }   
}

But the best I could get is this (one ArrayList<Integer> with the correct values and order):

[-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1]

Any help would be greatly appreciated.



Solution 1:[1]

Here is one way.

  • stream the original list of lists
  • then stream each list and map a boolean to the desired value.
  • creating a list of lists
List<List<Boolean>> lists = List.of(
        List.of(true, true, true, false, false, false),
        List.of(true, true, false, false, false),
        List.of(true, true, true, false, false, false));

List<List<Integer>> result = lists.stream()
    .map(list -> list.stream().map(v -> v ? -1 : 1)
        .toList())
    .toList();

result.forEach(System.out::println);

prints

[-1, -1, -1, 1, 1, 1]
[-1, -1, 1, 1, 1]
[-1, -1, -1, 1, 1, 1]

Note v ? -1 or 1 says if v is true, use -1 else use 1.

Solution 2:[2]

In order to create a nested list (List<List<T>>) at each step of iteration of the outer for loop you have to create a new List and populate it with the data for the current month inside the inner for loop. This list needs to be added into the resulting nested list.

    List<List<Integer>> intByMonth = new ArrayList<>();

    for (List<Boolean> arr : isExpenseByMonth) {
        List<Integer> nextMonth = new ArrayList<>();
        for (boolean b : arr) {
            nextMonth.add(b ? -1 : 1);
        }
        intByMonth.add(nextMonth);
    }

Note:

  • Don't use concrete implementations like ArrayList as a type, it makes your code inflexible and unnecessarily verbose. Write the code against interfaces (List, Map, etc.). This approach is called Dependency inversion principle.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 WJS
Solution 2