如何在Java中将List <Integer>转换为int []?

545 java arrays collections

这类似于这个问题: 如何在Java中将int []转换为Integer []?

我是Java的新手.我怎么能转换List<Integer>int[]Java中?我很困惑,因为List.toArray()实际上返回一个Object[],可以强制转换为虚空Integer[]int[].

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

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;
}
Run Code Online (Sandbox Code Playgroud)

我相信有更好的方法可以做到这一点.

Psh*_*emo 565

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

int[] array = list.stream().mapToInt(i->i).toArray();
Run Code Online (Sandbox Code Playgroud)

思考过程:

  • 简单的Stream#toArray回报Object[],所以它不是我们想要的.也Stream#toArray(IntFunction<A[]> generator)不会做出我们想要的东西,因为泛型类型A不能代表原int
  • 所以有一些可以处理原始类型的流会很好int,因为它的Integer方法很可能也会返回toArray数组(返回其他类似的东西int[],甚至盒装Object[]在这里会不自然).幸运的是Java 8有这样的流:Integer[]
  • 所以现在我们唯一需要弄清楚的是如何将我们IntStream(将从中返回Stream<Integer>)转换为闪亮的list.stream().这里的IntStream方法来救援.所有我们需要做的就是提供一些映射Stream#mapToInt(ToIntFunction<? super T> mapper)Integer.我们可以使用类似int返回的东西Integer#getValue:

    int

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

    但是类似的代码可以使用unboxing生成,因为编译器知道这个lambda的结果必须是int(lambda in mapToIntToIntFunction接口的实现,它期望body int applyAsInt(T value)返回预期的方法int).

    所以我们可以简单地写

    Integer

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

    Stream#toArray

  • @PimpTrizkit稍微更新了这个答案.希望现在更清楚了. (10认同)
  • 显然是最好的解决方案。太糟糕了,它缺乏解释。 (4认同)
  • @Pshemo - 谢谢!我个人不需要解释。但我讨厌看到没有一个的完美答案!无论如何,您的解释确实教育了我并且很有帮助。我想知道为什么 `mapTo...` 函数不允许 `null` lambda.... 就像 sort 一样......这使它默认为默认行为......在这种情况下,`i -&gt; i` 将是一个完美的默认行为。 (2认同)
  • @vefthym我没有测试它,但我怀疑这两种解决方案都遵循相同的简单原理,因此我期望相似的速度(但请随意对其进行基准测试)。这个答案的一个优点是,只要我们有 Java 8,它就不需要额外的库。 (2认同)

Jon*_*eet 208

不幸的是,我不相信有真的这样做由于Java的处理基本类型,拳击,数组和仿制药的性质的更好的方法.特别是:

  • List<T>.toArray将无法正常工作,因为没有转换Integerint
  • 你不能将它int作为泛型的类型参数使用,因此它必须是一种int特定的方法(或者使用反射来做恶劣的诡计).

我相信有些库可以为所有原始类型提供这种方法的自动生成版本(即有一个模板可以为每种类型复制).这很难看,但这就是我害怕的方式:(

即使Arrays该类在泛型到达Java之前出现,如果它今天被引入,它仍然必须包括所有可怕的重载(假设你想使用原始数组).

  • 另请参阅ColinD关于番石榴的Ints.toArray(Collection <Integer>)的答案 (30认同)
  • @JonSkeet你的意思是像'binarySearch`,`copyOf`,`copyOfRange` ......的Arrays类中已经存在的可怕的重载一样?我想知道他们为什么不能添加另一组可怕的重载. (6认同)
  • @bvdb:我说没有其他库(基本上还有循环,但代码不是你的),我不相信有更好的方法.这是一个明显更强的断言,而不是说我不知道​​是否有更好的方法. (2认同)

Col*_*inD 195

除了Commons Lang,你可以用Guava的方法做到这一点Ints.toArray(Collection<Integer> collection):

List<Integer> list = ...
int[] ints = Ints.toArray(list);
Run Code Online (Sandbox Code Playgroud)

这可以节省您必须进行Commons Lang等效的中间数组转换.

  • "幸运的是,中间阵列隐藏在番石榴内." - 修正了你.;) (4认同)
  • 不幸的是,中间数组隐藏在Guava中:`Object [] boxedArray = collection.toArray();` (3认同)

Edd*_*die 170

最简单的方法是使用Apache Commons Lang.它有一个方便的ArrayUtils类,可以做你想要的.toPrimitive对于Integers 数组,请使用带有重载的方法.

List<Integer> myList;
 ... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));
Run Code Online (Sandbox Code Playgroud)

这样你就不会重新发明轮子.Commons Lang有许多Java遗漏的有用的东西.在上面,我选择创建一个正确大小的整数列表.您还可以使用0长度的静态Integer数组,让Java分配一个正确大小的数组:

static final Integer[] NO_INTS = new Integer[0];
   ....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这需要2个分配和副本:`myList.toArray()`将创建一个`Integer []`并填充它,而`ArrayUtils.toPrimitive()`将分配一个`int []`并取消输入输入. (10认同)

Pum*_*use 55

Java 8通过流程为我们提供了一种简单的方法...

使用集合stream()函数然后映射到整数,您将获得一个IntStream.随着IntStream我们可以称之为指定者(),它给了我们int []

int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
Run Code Online (Sandbox Code Playgroud)

到int []

到IntStream


小智 51

int[] toIntArray(List<Integer> list)  {
    int[] ret = new int[list.size()];
    int i = 0;
    for (Integer e : list)  
        ret[i++] = e;
    return ret;
}
Run Code Online (Sandbox Code Playgroud)

对代码稍作更改以避免昂贵的列表索引(因为List不一定是ArrayList,但可能是链表,随机访问很昂贵)

  • 该方法将List作为参数,并非所有实现都具有快速随机访问(如ArrayList) (5认同)

Noo*_*waz 12

这是Java 8单行代码

public int[] toIntArray(List<Integer> intList){
       return intList.stream().mapToInt(Integer::intValue).toArray();
}
Run Code Online (Sandbox Code Playgroud)


Lod*_*ijk 7

我会在这里多扔一个.我注意到for循环的几种用法,但你甚至不需要循环内的任何东西.我之所以提到这一点,只是因为最初的问题是试图找到更简洁的代码.

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;
}
Run Code Online (Sandbox Code Playgroud)

如果Java允许在C循环中使用for循环中的多个声明,我们可以更进一步做(int i = 0,Iterator it ...

最后虽然(这部分仅仅是我的观点),如果您将有一个帮助功能或方法为您做某事,只需设置它并忘记它.它可以是一行或十行; 如果你再也不会看到它,你就不会知道它的区别.


Mr.*_*irl 7

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

int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();
Run Code Online (Sandbox Code Playgroud)

请注意这一点

请注意,并行性不会比串行执行操作更快,尽管可能有足够的数据和处理器内核.虽然聚合操作使您能够更轻松地实现并行性,但您仍有责任确定您的应用程序是否适合并行性.


将Integers映射到其原始形式有两种方法:

  1. 通过ToIntFunction.

    mapToInt(Integer::intValue)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 通过使用lambda表达式显式取消装箱.

    mapToInt(i -> i.intValue())
    
    Run Code Online (Sandbox Code Playgroud)
  3. 通过使用lambda表达式隐式(自动)拆箱.

    mapToInt(i -> i)
    
    Run Code Online (Sandbox Code Playgroud)

给出一个带有null值的列表

List<Integer> list = Arrays.asList(1, 2, null, 4, 5);
Run Code Online (Sandbox Code Playgroud)

以下是三个选项null:

  1. null在映射之前过滤掉值.

    int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
    
    Run Code Online (Sandbox Code Playgroud)
  2. null值映射到默认值.

    int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
    
    Run Code Online (Sandbox Code Playgroud)
  3. 处理nulllambda表达式.

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


THA*_*rum 6

这个简单的循环总是正确的!没有错误

  int[] integers = new int[myList.size()];
  for (int i = 0; i < integers.length; i++) {
      integers[i] = myList.get(i);
  }
Run Code Online (Sandbox Code Playgroud)

  • “有效”与“理想”不一样,性能问题可以被认为是错误。`List#get(int)` 不能保证是一个恒定时间的操作,正如你可能已经假设的那样,所以它不应该用于迭代。相反,请使用专为此用例设计的迭代器。要么使用 Java 5+ foreach 循环,要么调用 `List#iterator()` 并使用迭代器。此外,在此循环期间列表的大小可能会发生变化,从而导致“IndexOutOfBoundsException”或不完整的数组。许多迭代器实现都有详细记录的策略来处理这种情况。 (2认同)

nee*_*esh 5

因为toArray返回一个Object []并且你不能从Object []转换为int []或Integer []转换为int [],所以实际上没有办法"单行".

  • 由于数组协方差,你可以*在Object []和Integer []之间进行转换 - 但是你不能在int []和Integer []之间进行转换. (4认同)