Search code examples
javamultidimensional-arraycollectionsround-robin

Join lists in java in round robin fashion


I need to round robin multiple ArrayLists in java. Is there any simple way to achieve it?

lists = [1,2,3], [4,5], [6,7,8]

Result should be:

[1,4,6,2,5,7,3,8]

Solution

  • tl;dr

    Loop the list of lists, looping for the maximum size. Pull the nth element from each list. The shorter lists will throw an exception when we ask for the nth element beyond their size; just ignore that exception.

    List < List < Integer > > listOfLists =
            List.of(
                    List.of( 1 , 2 , 3 ) ,
                    List.of( 4 , 5 ) ,
                    List.of( 6 , 7 , 8 )
            );
    OptionalInt longestLength = listOfLists.stream().mapToInt( List :: size ).max();
    int limit = longestLength.orElse( 0 );
    
    int initialCapacity = listOfLists.stream().mapToInt( List :: size ).sum();
    List < Integer > results = new ArrayList <>( initialCapacity );
    
    for ( int i = 0 ; i < limit ; i++ )
    {
        for ( List < Integer > listOfIntegers : listOfLists )
        {
            try
            {
                Integer integer = listOfIntegers.get( i );
                results.add( integer );
            }
            catch ( IndexOutOfBoundsException e )
            {
                // Do nothing. Swallow exception. We expect to fall out of bounds on shorter lists.
            }
        }
    }
    return List.copyOf( results ) ;
    

    This approach might be improved by checking to see if we went past the end of the shorter arrays, rather than throwing an exception. But in this case I do not see much point in that.

    Details

    Define our lists.

    List < List < Integer > > listOfLists =
            List.of(
                    List.of( 1 , 2 , 3 ) ,
                    List.of( 4 , 5 ) ,
                    List.of( 6 , 7 , 8 )
            );
    

    listOfLists.toString() = [[1, 2, 3], [4, 5], [6, 7, 8]]

    Determine the longest length of the lists.

    OptionalInt longestLength = listOfLists.stream().mapToInt( List :: size ).max();
    int limit = longestLength.orElse( 0 ); 
    

    longestLength.toString() = OptionalInt[3]

    limit = 3

    Build a list to capture our results.

    int initialCapacity = listOfLists.stream().mapToInt( List :: size ).sum();
    List < Integer > results = new ArrayList <>( initialCapacity );
    

    Loop through each list, ignoring any IndexOutOfBoundsException thrown on the shorter lists.

    for ( int i = 0 ; i < limit ; i++ )
    {
        for ( List < Integer > listOfIntegers : listOfLists )
        {
            try
            {
                Integer integer = listOfIntegers.get( i );
                results.add( integer );
            }
            catch ( IndexOutOfBoundsException e )
            {
                // Do nothing. Swallow exception. We expect to fall out of bounds on shorter lists.
            }
        }
    }
    

    See this code run live at IdeOne.com.

    results = [1, 4, 6, 2, 5, 7, 3, 8]

    Return an unmodifiable list of those numbers.

    return List.copyOf( results ) ;