关于数组:如何转换List< Integer>

How to convert List<Integer> to int[] in Java?

本问题已经有最佳答案,请猛点这里访问。

这类似于这个问题:如何在Java中转换int []到整数[]?

我是爪哇人。在Java中,如何将EDCOX1的0度转换为EDCOX1×1?我很困惑,因为List.toArray()实际上返回了一个Object[],可以投射到下一个Integer[]int[]

现在,我正在使用一个循环来执行此操作:

1
2
3
4
5
6
int[] toIntArray(List<Integer> list){
  int[] ret = new int[list.size()];
  for(int i = 0;i < ret.length;i++)
    ret[i] = list.get(i);
  return ret;
}

我相信有更好的办法。


没有人提到在Java 8中添加的流,所以这里是:

1
int[] array = list.stream().mapToInt(i->i).toArray();

思维过程:

  • simple Stream#toArray返回Object[],所以它不是我们想要的。另外,Stream#toArray(IntFunction generator)不做我们想要的,因为泛型类型A不能表示原始int
  • 因此,最好有一些可以处理原始类型int的流,因为它的toArray方法很可能也会返回int[]数组(返回类似于Object[]或甚至装箱的Integer[]的其他内容在这里是不自然的)。幸运的是,Java 8具有这样的流:EDCOX1×10
  • 所以现在我们唯一需要考虑的是如何将我们的Stream(将从list.stream())转换成闪亮的IntStream。在这里,江户十一〔14〕法来拯救。我们需要做的只是提供一些从Integerint的映射。我们可以使用像Integer#getValue这样的返回int的东西:

    mapToInt( (Integer i) -> i.intValue())

    (或者如果有人更喜欢mapToInt(Integer::intValue))

    但是可以使用拆箱生成类似的代码,因为编译器知道这个lambda的结果必须是int(mapToInt中的lambda是ToIntFunction接口的实现,该接口期望int applyAsInt(T value)方法的主体,该方法期望返回int

    所以我们可以简单地写

    mapToInt((Integer i)->i)

    或者更简单(因为List#stream()返回Stream,所以编译器可以推断Integer i类型)

    mapToInt(i -> i)


不幸的是,由于Java处理原始类型、装箱、数组和泛型的性质,我不认为确实有更好的方法来实现这一点。特别地:

  • List.toArray不起作用,因为没有从Integerint的转换。
  • 不能将int用作泛型的类型参数,因此它必须是int特定的方法(或使用反射进行恶意欺骗的方法)。

我相信有一些库可以为所有的基元类型自动生成这种方法的版本(也就是说,有一个为每种类型复制的模板)。很难看,但恐怕是这样的:(

尽管EDCOX1的5个类在泛型到达Java之前就已经出来了,但是如果它现在被引入的话,它仍然必须包括所有可怕的重载(假设你想使用原始数组)。


除了commons lang之外,您还可以使用guava的方法Ints.toArray(Collection collection)来执行此操作:

1
2
List<Integer> list = ...
int[] ints = Ints.toArray(list);

这就省去了您必须执行commons-lang等价物所需的中间数组转换。


最简单的方法是利用ApacheCommonsLang,它有一个方便的arrayUtils类,可以实现您想要的。对一个Integers数组使用带重载的toPrimitive方法。

1
2
3
List<Integer> myList;
 ... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));

这样你就不会重新发明轮子了。公文郎有很多有用的东西,Java忽略了。上面,我选择创建一个大小合适的整数列表。还可以使用0长度的静态整数数组,并让Java分配一个正确大小的数组:

1
2
3
static final Integer[] NO_INTS = new Integer[0];
   ....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));


1
2
3
4
5
6
7
int[] toIntArray(List<Integer> list)  {
    int[] ret = new int[list.size()];
    int i = 0;
    for (Integer e : list)  
        ret[i++] = e;
    return ret;
}

为避免昂贵的列表索引,对代码进行细微的更改(因为列表不一定是ArrayList,但可能是一个链接列表,对于该列表,随机访问是昂贵的)


Java 8给了我们一个简单的方法,通过流…

使用collections stream()函数,然后映射到ints,您将得到一个intstream。使用IntStream,我们可以调用toarray(),它使我们得到int []

1
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();

INT[]

流入


这里是Java 8的单行代码

1
2
3
public int[] toIntArray(List<Integer> intList){
       return intList.stream().mapToInt(Integer::intValue).toArray();
}

如果您只是将一个Integer映射到一个int,那么您应该考虑使用并行性,因为您的映射逻辑不依赖于其范围之外的任何变量。

1
int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();

注意这个

Note that parallelism is not automatically faster than performing operations serially, although it can be if you have enough data and processor cores. While aggregate operations enable you to more easily implement parallelism, it is still your responsibility to determine if your application is suitable for parallelism.

有两种方法可以将整数映射到其原始形式:

  • 通过一个ToIntFunction

    1
    mapToInt(Integer::intValue)
  • 通过使用lambda表达式显式取消绑定。

    1
    mapToInt(i -> i.intValue())
  • 通过使用lambda表达式隐式(自动)取消绑定。

    1
    mapToInt(i -> i)
  • 给出一个具有null值的列表

    1
    List<Integer> list = Arrays.asList(1, 2, null, 4, 5);

    以下是处理null的三个选项:

  • 映射前过滤掉null值。

    1
    int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
  • null值映射到默认值。

    1
    int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
  • 在lambda表达式中处理null

    1
    int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();

  • 我再扔一个。我注意到for循环有几种用法,但您甚至不需要在循环中使用任何东西。我之所以提到这一点,只是因为最初的问题试图找到不那么冗长的代码。

    1
    2
    3
    4
    5
    6
    7
    8
    int[] toArray(List<Integer> list) {
        int[] ret = new int[ list.size() ];
        int i = 0;
        for( Iterator<Integer> it = list.iterator();
             it.hasNext();
             ret[i++] = it.next() );
        return ret;
    }

    如果Java允许以C++的方式在for循环中进行多个声明,那么我们可以进一步进行(int i=0,迭代器…

    但最后(这部分只是我的观点),如果你想有一个帮助的功能或方法来为你做一些事情,只需设置它并忘记它。它可以是一行,也可以是十行;如果你再也看不到它,你就不知道有什么区别。


    这个简单的循环总是正确的!没有虫子

    1
    2
    3
    4
      int[] integers = new int[myList.size()];
      for (int i = 0; i < integers.length; i++) {
          integers[i] = myList.get(i);
      }


    因为ToArray返回一个对象[],并且不能从对象[]强制转换为int[]或整数[]强制转换为int[]


    1
    2
    3
    4
    5
    6
    int[] ret = new int[list.size()];      
    Iterator<Integer> iter = list.iterator();
    for (int i=0; iter.hasNext(); i++) {      
        ret[i] = iter.next();                
    }                                        
    return ret;

    尝试美元(检查此修订版):

    1
    2
    3
    4
    5
    import static com.humaorie.dollar.Dollar.*
    ...

    List<Integer> source = ...;
    int[] ints = $(source).convert().toIntArray();

    使用Eclipse集合,如果有java.util.List类型的列表,则可以执行以下操作:

    1
    2
    3
    4
    List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
    int[] ints = LazyIterate.adapt(integers).collectInt(i -> i).toArray();

    Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);

    如果您已经有一个Eclipse集合类型,如MutableList,则可以执行以下操作:

    10

    注意:我是Eclipse集合的提交者


    我建议您从Java集合API中使用EDCOX1 9的骨架实现,在这种特殊情况下它似乎非常有用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    package mypackage;

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

    public class Test {

    //Helper method to convert int arrays into Lists
    static List<Integer> intArrayAsList(final int[] a) {
        if(a == null)
            throw new NullPointerException();
        return new AbstractList<Integer>() {

            @Override
            public Integer get(int i) {
                return a[i];//autoboxing
            }
            @Override
            public Integer set(int i, Integer val) {
                final int old = a[i];
                a[i] = val;//auto-unboxing
                return old;//autoboxing
            }
            @Override
            public int size() {
                return a.length;
            }
        };
    }

    public static void main(final String[] args) {
        int[] a = {1, 2, 3, 4, 5};
        Collections.reverse(intArrayAsList(a));
        System.out.println(Arrays.toString(a));
    }
    }

    小心拳击/拆箱的缺点


    使用lambda可以做到这一点(在JDK lambda中编译):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public static void main(String ars[]) {
            TransformService transformService = (inputs) -> {
                int[] ints = new int[inputs.size()];
                int i = 0;
                for (Integer element : inputs) {
                    ints[ i++ ] = element;
                }
                return ints;
            };

            List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };

            int[] results = transformService.transform(inputs);
        }

        public interface TransformService {
            int[] transform(List<Integer> inputs);
        }