将一个原始long数组转换为Longs列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将一个原始long数组转换为Longs列表相关的知识,希望对你有一定的参考价值。
这可能是一个简单的问题,但是我的第一次尝试完全失败了。我想取一个原始long的数组并将其转换为一个列表,我尝试这样做:
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
这样做的正确方法是什么?
我发现使用apache commons lang ArrayUtils很方便(JavaDoc,Maven dependency)
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);
编辑:已更新,可根据评论和其他修正提示完整转换为列表。
问题是关于如何将数组转换为列表。到目前为止,大多数答案都显示了如何使用与数组相同的内容创建新列表,或者引用第三方库。但是,这种转换有简单的内置选项。其中一些已经在其他答案中勾勒出来(例如this one)。但我想在此指出并阐述实施的某些自由度,并展示潜在的好处,缺点和警告。
至少有两个重要的区别:
- 结果列表是否应该是数组上的视图,或者它是否应该是新列表
- 结果列表是否应该是可修改的
这里将快速总结选项,并在本答案的底部显示完整的示例程序。
创建新列表与在阵列上创建视图
当结果应该是新列表时,可以使用其他答案中的一种方法:
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?
可以在可修改的数组上创建列表视图。这意味着列表中的更改(如在某个索引处设置新值)将在数组中可见。
但是无法创建结构可修改的列表视图。这意味着无法执行影响列表大小的操作。这只是因为底层数组的大小无法更改。
以下是MCVE,显示了不同的实现选项,以及使用结果列表的可能方法:
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
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);
return new AbstractList<Long>()
{
@Override
public Long get(int index)
{
return array[index];
}
@Override
public int size()
{
return array.length;
}
};
}
/**
* 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);
return new AbstractList<Long>()
{
@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;
}
};
}
}
此示例的输出如下所示:
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]
Chan以上是关于将一个原始long数组转换为Longs列表的主要内容,如果未能解决你的问题,请参考以下文章
我可以使用 Java 8 的 stream() 将一组非原始项转换为列表吗? [复制]