Collecting a collection of list based on similar index

You can use a Map to group the values by index:

Map<Integer, List<Object>> map = new TreeMap<>();
for (List<Object> objects : firstList) {
    for (int i = 0, l = objects.size(); i < l; i++) {
        map.computeIfAbsent(i, k -> new ArrayList<>()).add(objects.get(i));
    }
}

And then to get the List back:

List<List<Object>> secondList = new ArrayList<>(map.values());

Assuming the lists inside the main list are all the same size, you can do something like this...

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;

    public class OhCrikey {

        public static void main(String[] args) {
            List<List<String>> lists = Arrays.asList(
                    Arrays.asList("1a", "2a", "3a"),
                    Arrays.asList("1b", "2b", "3b"),
                    Arrays.asList("1c", "2c", "3c")
            );

            List<List<String>> result = transform(lists);

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

        private static <T> List<List<T>> transform(List<List<T>> lists) {
            if(lists == null || lists.isEmpty()) {
                return Collections.emptyList();
            }
            // Check each sub-list contains the same number of elements
            checkAllSameSize(lists);

            // Initialise the results list
            List<List<T>> result = new ArrayList<>();

            // Get the size of each sub-list
            int totalLists = lists.get(0).size();

            // Fill up the results list with 'totalLists' empty lists
            for(int k = 0; k < totalLists; k++) {
                result.add(new ArrayList<>());
            }

            // For each input list...
            lists.forEach(list -> {
                // Iterate over it and add the kth element to the kth result list.
                for(int k = 0; k < list.size(); k++) {
                    result.get(k).add(list.get(k));
                }
            });

            return result;
        }

        private static <T> void checkAllSameSize(List<List<T>> lists) {
            int size = lists.get(0).size();

            // Make sure each list has the same size as the first list
            lists.forEach(list -> {
                if(list.size() != size) {
                    throw new AssertionError("All child lists must have same number of elements.");
                }
            });
        }
    }

Prints...

    [1a, 1b, 1c]
    [2a, 2b, 2c]
    [3a, 3b, 3c]

First, get the max length of a sublist. In your case, both are 3. Iterate over all these indices, getting the value from each sublist at this index and collecting those to a new sublist.

final int maxLengthOfSublist = list1.stream().mapToInt(List::size).max().orElse(0);
final List<List<Integer>> list2 = IntStream.range(0, maxLengthOfSublist)
    .mapToObj(idx -> list1.stream()
        .filter(sublist -> idx < sublist.size())
        .map(sublist -> sublist.get(idx))
        .collect(Collectors.toList())
    )
    .collect(Collectors.toList());

This will work even if the sublists are different lengths.