简体   繁体   English

如何创建ArrayList(ArrayList <T> )从基本类型元素的数组

[英]How to create ArrayList (ArrayList<T>) from array of primitive type elements

public class Main {

public static void main(String[] args) {
    byte[] a=new byte[3];
    List<Byte> c=new ArrayList<Byte>();

    c.addAll(Arrays.asList(a)); 
    //The method addAll(Collection<? extends Byte>) in the type List<Byte> 
    //is not applicable for the arguments (List<byte[]>)

    Collections.addAll(c, a);
    //The method addAll(Collection<? super T>, T...) in the type Collections 
    //is not applicable for the arguments (List<Byte>, byte[])

}

}

Last two lines give compile error. 最后两行给出编译错误。

To fix it, firstly I read this Create ArrayList from array discussing. 为了解决这个问题,首先我从数组讨论中读取了此Create ArrayList I try this solution, but it don't work. 我尝试了这种解决方案,但是它不起作用。 Here Converting array to list in Java is explain, why it don't work, but isn't solution. 这里解释了如何在Java中将数组转换为列表 ,为什么它不起作用,但不是解决方案。

"source array is a primitive array of bytes, instead of Byte objects" is true, and I hope, that exists more beautibul solution, then iterate and cast each element. “源数组是字节的原始数组,而不是字节对象”是正确的,我希望存在更多的美丽解决方案,然后迭代并转换每个元素。

Your array must be an array of Byte, not byte. 您的数组必须是字节数组,而不是字节数组。 addAll requires a collection of objects that match. addAll需要匹配的对象的集合。

In other words: Byte[] a=new Byte[3]; 换句话说:Byte [] a = new Byte [3];

Alternatively, if your source array is a primitive array of bytes, instead of Byte objects, then you have to loop through them and add one at a time: 另外,如果您的源数组是原始的字节数组,而不是Byte对象,则必须遍历它们并一次添加一个:

for( byte toInsert: a ){
   c.add((Byte)a);// Probably don't need the cast, but included for clarity
}

It is not possible with standard Java to have Collections on primitive types. 标准Java不可能在基本类型上具有Collections。 However there are some libraries available (like trove or apache commons primitives ) to achieve this. 但是,有一些可用的库(例如troveapache commons原语 )可以实现此目的。

This has great performance implications. 这具有很大的性能影响。 The Boxed Types of the primitives have a massive amount of (mostly unneeded) overhead, because every boxed object extends the java basic Object (i think the overhead is somewhere at 8 bytes per object). 原语的Boxed Types具有大量(几乎不需要)开销,因为每个Boxed对象都扩展了Java Basic Object (我认为每个对象的开销约为8个字节)。 I a List with for instance 1000 Integers you have 1000 times the overhead, which can be bad for your memory. 我有一个列表,例如1000个Integer,那么您的开销是1000倍,这可能对您的内存不利。 So if memory consumption is an issue, primitive collections are a great way to deal with it. 因此,如果内存消耗是一个问题,则原始集合是解决此问题的好方法。

If Memory conspumtion is not a problem, you can use the boxed types and jazees answer 如果内存消耗不成问题,则可以使用带框的类型和jazees答案

With Java 8 you can use streams do it in a single statement, without the casting and iteration you want to avoid: 使用Java 8,您可以使用流在单个语句中完成操作,而无需进行强制转换和迭代:

byte[] byteArray = {-128, 89, 103, 92, 0, 127};
List<Byte> byteList = IntStream.range(0, byteArray.length) 
                               .mapToObj((int i) -> byteArray[i]) 
                               .collect(Collectors.toList()); 
System.out.println("byteList = " + byteList);

The basic idea is to get the array values into a Stream, then load those stream values into a List: 基本思想是将数组值放入Stream中,然后将这些流值加载到List中:

  • range() yields an IntStream 0,1,2,3,4,5 corresponding to the index range()产生一个与索引相对应的IntStream 0、1、2、3、4、5
    values in the byte array. 字节数组中的值。
  • mapToObj() yields a Stream -128, 89, 103, 92, 0, 127 corresponding to the byte array's values. mapToObj()产生与字节数组的值相对应的Stream -128、89、103、92、0、127。
  • collect() puts those stream values into a List. collect()将这些流值放入列表中。

You can use the same approach for char[] and short[] transformations. 您可以对char []和short []转换使用相同的方法。

In Java, there are classes that "wrap" around primitive types, so to speak. 可以这么说,在Java中,有些类可以“包装”原始类型。 These classes are: Integer, Byte, Long, Double, Float, Character, etc. 这些类是:整数,字节,长整数,双精度,浮点数,字符等。

Now here are the primitive types: int, byte, long, double, float, char, etc. 现在这里是原始类型:int,byte,long,double,float,char等。

You see the similarity? 您看到相似之处了吗? So when you are using type parameters (notated like this: ), you have to use these wrapper classes instead of the primitive types because primitives aren't classes (that's why String isn't a primitive but it is a class.) You can add primitive types like "byte b = 1" to the list you have up there, but because the array you have doesn't match the class of your list, it doesn't work. 因此,当您使用类型参数(用这样的符号表示:)时,您必须使用这些包装类而不是原始类型,因为原始不是类(这就是为什么String不是原始但它是一个类的原因。)将原始类型(例如“ byte b = 1”)添加到您所在的列表中,但是由于您拥有的数组与列表的类不匹配,因此无法使用。

It's an easy fix, just changed the type of your array from "byte" to "Byte." 这很容易解决,只需将数组的类型从“字节”更改为“字节”即可。

The simple way I would recommend to new programmers: 我向新程序员推荐的简单方法是:

static ArrayList<Integer> primitiveArrayToArrayList(int[] input)
{
    ArrayList<Integer> result = new ArrayList<>();
    for (int i : input)
        result.add(i);
    return result;
}

The modern way I would recommend to advanced programmers: 我向高级程序员推荐的现代方式:

static ArrayList<Integer> primitiveArrayToArrayList(int[] input)
{
    return Arrays.stream(input).boxed().collect(Collectors.toCollection(ArrayList::new));
}

note: Arrays.stream() is only available for int, long, double and reference types 注意:Arrays.stream()仅适用于int,long,double和reference类型

This way allows simple modifications in a more complex use case, like here: 这种方式允许在更复杂的用例中进行简单的修改,例如:

static ArrayList<Integer> findValues(int[] input, Predicate<Integer> filter, int limit)
{
    return Arrays.stream(input).boxed().filter(filter).limit(limit).collect(Collectors.toCollection(ArrayList::new));
}

public static void main(String[] args)
{
    int[] values = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    Predicate<Integer> filter = i -> i % 2 == 0;
    int limit = 3;

    System.out.println(findValues(values, filter, limit));
}

converting the Array to an ArrayList, while filtering for even numbers and limit the result size to 3 results in: 将Array转换为ArrayList,同时过滤偶数并将结果大小限制为3,结果是:

out: [0, 2, 4]

Stream API chain vs. loop 流API链与循环

static ArrayList<Integer> findValues(int[] input, Predicate<Integer> filter, int limit)
{
    return Arrays.stream(input).boxed().filter(filter).limit(limit).collect(Collectors.toCollection(ArrayList::new));
}

static ArrayList<Integer> findValues(int[] input, Predicate<Integer> filter, int limit)
{
    ArrayList<Integer> integers = new ArrayList<>();
    for (int i : input)
    {
        if (filter.test(i))
        {
            if (limit-- == 0) break;
            integers.add(i);
        }
    }
    return integers;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM