这可能是一个非常简单的问题,但我的第一次尝试居然完全失败了。我想把一个原始长整型数组转换成列表,我尝试用以下代码实现:
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
如何正确地做到这一点?
这可能是一个非常简单的问题,但我的第一次尝试居然完全失败了。我想把一个原始长整型数组转换成列表,我尝试用以下代码实现:
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
如何正确地做到这一点?
自Java 8起,您现在可以使用流来实现此操作:
long[] arr = { 1, 2, 3, 4 };
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
stream
函数只定义了 int[]
、long[]
和 double[]
这几种类型。 - NorswapLongStream.of(arr).boxed()...
。 - aioobeArrays.stream(arr).boxed().collect(Collectors.toList());
不幸的是,这只能返回 List<Object>
。 - Senthilkumar AnnaduraiList<Long>
。 - Lii我发现使用Apache Commons Lang ArrayUtils (JavaDoc, Maven依赖)很方便。
import org.apache.commons.lang3.ArrayUtils;
...
long[] input = someAPI.getSomeLongs();
Long[] inputBoxed = ArrayUtils.toObject(input);
List<Long> inputAsList = Arrays.asList(inputBoxed);
它还具有反向API。
long[] backToPrimitive = ArrayUtils.toPrimitive(objectArray);
编辑: 根据评论提供完整的列表转换,以及其他修复。
Arrays.asList(ArrayUtils.toObject(input))
这个操作。 - Eran MedanList<Long> = Arrays.asList(inputBoxed)
,我认为重复它是多余的,因为我认为这是显而易见的,但我错了... - Eran Medanimport java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;
List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));
稍微多了点描述,但这个方法可行:
List<Long> list = new ArrayList<Long>();
for (long value : input) {
list.add(value);
}
在你的例子中,Arrays.asList()似乎将输入解释为long[]数组的列表而不是Long类型的列表。这确实有些令人惊讶。自动装箱在这种情况下并不能按照你想要的方式工作。
作为另一个可能性,Guava库 提供了 Longs.asList()
方法,还提供了其他原始类型的类似实用程序类。
import com.google.common.primitives.Longs;
long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);
至少需要做两个重要的区分:
这里将快速总结选项,并在本答案底部展示完整的示例程序。
创建新列表与在数组上创建视图
当结果应该是新列表时,可以使用其他答案中的一种方法:
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
但是,我们也应该考虑这样做的缺点:一个包含1000000个long
值的数组将占用大约8兆字节的内存。而新列表也将占用大约8兆字节的内存。当然,在创建这个列表时,整个数组必须被遍历。在许多情况下,创建一个新的列表并不是必要的。相反,只需在数组上创建一个视图即可。
// This occupies ca. 8 MB
long array[] = { /* 1 million elements */ }
// Properly implemented, this list will only occupy a few bytes,
// and the array does NOT have to be traversed, meaning that this
// operation has nearly ZERO memory- and processing overhead:
List<Long> list = asList(array);
(请参见底部的示例,了解toList
方法的实现)
拥有对数组的视图意味着数组中的更改将在列表中可见:
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
System.out.println(list.get(1)); // This will print 34
// Modify the array contents:
array[1] = 12345;
System.out.println(list.get(1)); // This will now print 12345!
幸运的是,从视图创建一个副本(即,一个新列表,不受数组修改的影响)非常简单:
List<Long> copy = new ArrayList<Long>(asList(array));
long array[] = { 12, 34, 56, 78 };
List<Long> list = asList(array);
list.set(2, 34567); // Should this be possible?
System.out.println(array[2]); // Should this print 34567?
list.set(3, null); // What should happen here?
list.add(99999); // Should this be possible?
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.RandomAccess;
public class PrimitiveArraysAsLists
{
public static void main(String[] args)
{
long array[] = { 12, 34, 56, 78 };
// Create VIEWS on the given array
List<Long> list = asList(array);
List<Long> unmodifiableList = asUnmodifiableList(array);
// If a NEW list is desired (and not a VIEW on the array), this
// can be created as well:
List<Long> copy = new ArrayList<Long>(asList(array));
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Modify a value in the array. The changes will be visible
// in the list and the unmodifiable list, but not in
// the copy.
System.out.println("Changing value at index 1 of the array...");
array[1] = 34567;
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Modify a value of the list. The changes will be visible
// in the array and the unmodifiable list, but not in
// the copy.
System.out.println("Changing value at index 2 of the list...");
list.set(2, 56789L);
System.out.println("array : " + Arrays.toString(array));
System.out.println("list : " + list);
System.out.println("unmodifiableList: " + unmodifiableList);
System.out.println("copy : " + copy);
// Certain operations are not supported:
try
{
// Throws an UnsupportedOperationException: This list is
// unmodifiable, because the "set" method is not implemented
unmodifiableList.set(2, 23456L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
// Throws an UnsupportedOperationException: The size of the
// backing array cannot be changed
list.add(90L);
}
catch (UnsupportedOperationException e)
{
System.out.println("Expected: " + e);
}
try
{
// Throws a NullPointerException: The value 'null' cannot be
// converted to a primitive 'long' value for the underlying array
list.set(2, null);
}
catch (NullPointerException e)
{
System.out.println("Expected: " + e);
}
}
/**
* Returns an unmodifiable view on the given array, as a list.
* Changes in the given array will be visible in the returned
* list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asUnmodifiableList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
/**
* Returns a view on the given array, as a list. Changes in the given
* array will be visible in the returned list, and vice versa. The
* list does not allow for <i>structural modifications</i>, meaning
* that it is not possible to change the size of the list.
*
* @param array The array
* @return The list view
*/
private static List<Long> asList(long array[])
{
Objects.requireNonNull(array);
class ResultList extends AbstractList<Long> implements RandomAccess
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public Long set(int index, Long element)
{
long old = array[index];
array[index] = element;
return old;
}
@Override
public int size()
{
return array.length;
}
};
return new ResultList();
}
}
示例的输出如下所示:
array : [12, 34, 56, 78]
list : [12, 34, 56, 78]
unmodifiableList: [12, 34, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 1 of the array...
array : [12, 34567, 56, 78]
list : [12, 34567, 56, 78]
unmodifiableList: [12, 34567, 56, 78]
copy : [12, 34, 56, 78]
Changing value at index 2 of the list...
array : [12, 34567, 56789, 78]
list : [12, 34567, 56789, 78]
unmodifiableList: [12, 34567, 56789, 78]
copy : [12, 34, 56, 78]
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.UnsupportedOperationException
Expected: java.lang.NullPointerException
使用Java 8的另一种方法。
long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));
long[] input = someAPI.getSomeLongs();
List<Long> lst = new ArrayList<Long>();
for(long l : input) lst.add(l);
我正在编写一个小型库,用于解决以下问题:
long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();