有什么体面的方法可以将多维数组转换为List <List <T >>?

时间:2019-09-11 04:50:59

标签: java arrays collections java-8 java-stream

当我们必须转换一维数组List类型时,我们可以简单地使用Arrays.asList()。但是在多维数组的背景下,我没有找到任何类似的东西。我必须手动创建一个List<List<T>>并按照原始多维数组填充值。       有什么体面的方法可以在这些类型之间进行转换? Java 8方式?

3 个答案:

答案 0 :(得分:4)

您可以使用Arrays.stream并映射内部数组:

<T> List<List<T>> toNestedList(T[][] array) {
    return Arrays.stream(array)
        .map(Arrays::asList)
        .collect(Collectors.toList());
}

这将创建一个内部数组流,将它们映射到列表并将所有内部列表收集到一个外部列表。

答案 1 :(得分:1)

当前提出的解决方案将创建一个新列表。这意味着必须遍历数组并必须分配内存。

类似于Arrays#asList,最好不要在给定数组上创建一个 new 列表,而只创建一个 view 。这样,即使数组包含1000000个元素,创建此列表视图的内存和性能开销实际上也是 zero

如何实现此示例:

import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.RandomAccess;

public class NestedAsList
{
    public static void main(String[] args)
    {
        String array[][] =
        {
            { "This", "is", "an" },
            { "example", "of", }, null,
            { "a", "jagged", "array" } 
        };

        List<List<String>> lists = asLists(array);
        lists.forEach(System.out::println);
    }

    /**
     * Returns a <i>view</i> on the given array, as a list where each element is
     * a <i>view</i> on the respective array element. When the array contains
     * <code>null</code> elements, then the list will contain an empty list at
     * this index.
     * 
     * @param array The array
     * @return The list view
     */
    private static <T> List<List<T>> asLists(T array[][])
    {
        Objects.requireNonNull(array);
        class ResultList extends AbstractList<List<T>> implements RandomAccess
        {
            @Override
            public List<T> get(int index)
            {
                T[] a = array[index];
                if (a == null)
                {
                    // Could return null or the empty list here...
                    return Collections.emptyList();
                }
                return Arrays.asList(a);
            }

            @Override
            public int size()
            {
                return array.length;
            }

        }
        return new ResultList();
    }
}

(顺便说一句:我想知道您从哪里获得多维通用数组。如今这应该很少见了……)


注意:答案已基于comment by Holger更新:让返回的列表也实现java.util.RandomAccess接口以表明答案是有益的具有固定时间索引访问。 Collections类中的许多静态实用程序方法都会检查给定列表是否为RandomAccess,并且在这种情况下能够更有效地执行其任务。

不幸的是,为了实现附加接口,必须创建一个新的本地类,但是这取决于结果类的使用方式,这可能是值得的。

asLists方法的原始实现是此方法,它只是返回了一个新的AbstractList not 实现了RandomAccess接口:

private static <T> List<List<T>> asLists(T array[][])
{
    Objects.requireNonNull(array);
    return new AbstractList<List<T>>()
    {

        @Override
        public List<T> get(int index)
        {
            T[] a = array[index];
            if (a == null)
            {
                // Could return null or the empty list here...
                return Collections.emptyList();
            }
            return Arrays.asList(a);
        }

        @Override
        public int size()
        {
            return array.length;
        }
    };
}

答案 2 :(得分:0)

以上解决方案是正确的,但不能处理2D数组中的空行,因此我在下面的解决方案中使用Java 8中的stream APIs,它也适用于空行和通用数组。

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class TwoDArrayToListOfList {
    public static void main(String[] args) {
        String [][] stringArray = new String[][]{{"John", "Alley", "Neon"}, {null}, {"Huston", "Gary"}, {"Ellen", "James", "Chris", "Jacob"}};
        List<List<String>> stringList = getListFrom2DArray(stringArray);
        stringList.forEach(list -> list.forEach(System.out::println));

        Integer [][] intArray = new Integer[][]{{1,3, 6}, {2, 4}, {null}, {6, 4, 3, 5}, {null}};
        List<List<Integer>> intList = getListFrom2DArray(intArray);
        intList.forEach(list -> list.forEach(System.out::println));

        Double [][] doubleArray = new Double[][]{{1.0,3.9, 6.7}, {2.4, 4.4}, {6.5, 4.1, 3.3, 5.2}, {null}};
        List<List<Double>> doubleList = getListFrom2DArray(doubleArray);
        doubleList.forEach(list -> list.forEach(System.out::println));
    }

    private static <T> List<List<T>> getListFrom2DArray(T[][] array) {
        return Arrays.stream(Objects.requireNonNull(array)).map(row -> Arrays.asList((row != null) ? row : (T[]) new Object[0])).collect(Collectors.toList());
    }
}