이것은 다소 쉬운 헤드 데스크 문제 일 수 있지만 첫 번째 시도는 놀랍게도 완전히 실패했습니다. 나는 원시적 인 long 배열을 가져 와서 목록으로 바꾸고 싶었습니다.
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
이것을하는 올바른 방법은 무엇입니까?
이것은 다소 쉬운 헤드 데스크 문제 일 수 있지만 첫 번째 시도는 놀랍게도 완전히 실패했습니다. 나는 원시적 인 long 배열을 가져 와서 목록으로 바꾸고 싶었습니다.
long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!
이것을하는 올바른 방법은 무엇입니까?
답변:
아파치 커먼즈 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))
아마 쉽게 할 수 있기 때문 입니다.
List<Long> = Arrays.asList(inputBoxed)
자신의 질문에 나는 그것이 명백했다 생각으로 그것을 반복 중복 발견, 내가 ... 내가 잘못 생각
Java 8부터는 다음과 같은 스트림을 사용할 수 있습니다.
long[] arr = {1,2,3,4};
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());
stream
함수는 int[]
, long[]
및에 대해서만 정의됩니다 double[]
.
LongStream.of(arr).boxed()...
.
Arrays.stream(arr).boxed().collect(Collectors.toList());
불행하게도 이것은 단지 반환 할 수 있습니다List<Object>
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;
List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));
hallidave 와 jpalecek 은 배열에 대해 올바른 아이디어를 가지고 있지만 다음과 같은 기능을 활용하지 않습니다 ArrayList
. 이 경우 목록의 크기가 알려져 있으므로를 만들 때 지정해야합니다 ArrayList
.
List<Long> list = new ArrayList<Long>(input.length);
for (long n : input)
list.add(n);
이런 식으로 불필요한 배열은 ArrayList
너무 짧아서 버릴 수 있도록 만들어 지지 않으며 ArrayList
공간 요구 사항을 과대 평가하여 빈 "슬롯"이 낭비되지 않습니다 . 물론 목록에 요소를 계속 추가하면 새로운 백업 배열이 필요합니다.
다른 가능성으로, 구아바 라이브러리 는이를 Longs.asList()
다른 기본 유형에 대한 유사한 유틸리티 클래스와 함께 로 제공합니다 .
import com.google.common.primitives.Longs;
long[] input = someAPI.getSomeLongs();
List<Long> output = Longs.asList(input);
이 질문은 배열을 목록으로 바꾸는 방법에 대해 물었습니다. 지금까지 대부분의 답변 은 배열과 동일한 내용을 사용하거나 타사 라이브러리를 참조하여 새 목록 을 만드는 방법을 보여주었습니다 . 그러나 이러한 종류의 변환에는 간단한 기본 제공 옵션이 있습니다. 그들 중 일부는 이미 다른 답변 (예 : this one ) 으로 스케치되었습니다 . 그러나 나는 여기서 구현에 대한 특정 자유도를 지적하고 구체화하고 잠재적 이점, 단점 및 경고를 보여주고 싶습니다.
최소한 두 가지 중요한 차이점이 있습니다.
옵션은 여기에 빠르게 요약되며이 예제의 맨 아래에 완전한 예제 프로그램이 표시됩니다.
새 목록 만들기와 배열 에서 보기 만들기
결과가 새로운 목록 이어야하는 경우 다른 답변의 접근 방식 중 하나를 사용할 수 있습니다.
List<Long> list = Arrays.stream(array).boxed().collect(Collectors.toList());
그러나이 작업의 단점을 고려해야합니다. 1000000 개의 long
값을 가진 배열 은 약 8MB의 메모리를 차지합니다. 새로운 목록 도 약 8MB를 차지할 것 입니다. 물론이 목록을 작성하는 동안 전체 배열을 순회해야합니다. 많은 경우 새 목록을 만들 필요가 없습니다. 대신 배열 에서 보기 를 작성하면 충분합니다 .
// 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;
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
이 문제에 대한 작은 라이브러리를 작성 중입니다.
long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();
Pavel과 Tom의 답변을 결합하면 다음과 같이됩니다.
@SuppressWarnings("unchecked")
public static <T> List<T> asList(final Object array) {
if (!array.getClass().isArray())
throw new IllegalArgumentException("Not an array");
return new AbstractList<T>() {
@Override
public T get(int index) {
return (T) Array.get(array, index);
}
@Override
public int size() {
return Array.getLength(array);
}
};
}
비슷한 의미를 원한다면 (아마도를 통해 Arrays.asList
) 고객 구현을 작성하거나 다른 사람의 고객 구현을 사용해야 합니다. 상자 및 상자의 값만 동일한 구현을 가져야 합니다.List
AbstractList
Arrays.asList
변형 을 사용할 수 있습니다 :
Transmorph transmorph = new Transmorph(new DefaultConverters());
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {});
예를 들어 source가 int 배열 인 경우에도 작동합니다.
나는이 질문이 충분히 오래되었다는 것을 알고 있지만 ... 자신 만의 변환 방법을 작성할 수도 있습니다.
@SuppressWarnings("unchecked")
public static <T> List<T> toList(Object... items) {
List<T> list = new ArrayList<T>();
if (items.length == 1 && items[0].getClass().isArray()) {
int length = Array.getLength(items[0]);
for (int i = 0; i < length; i++) {
Object element = Array.get(items[0], i);
T item = (T)element;
list.add(item);
}
} else {
for (Object i : items) {
T item = (T)i;
list.add(item);
}
}
return list;
}
정적 가져 오기를 사용하여 포함시킨 후 가능한 사용법은 다음과 같습니다.
long[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<Long> list = toList(array);
또는
List<Long> list = toList(1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l);
catch (ArrayIndexOutOfBoundsException ex) { /* Finished getting array elements */ }
당신은 끔찍한 사람입니다.
for 루프 또는 스트림을 통해 새 List를 만들고 모든 값을 추가 할 수는 있지만 실제로 큰 배열을 작업하고 성능이 저하되었습니다. 따라서 사용하기 쉬운 기본 배열 래퍼 클래스를 만들었습니다.
예:
long[] arr = new long[] {1,2,3};
PrimativeList<Long> list = PrimativeList.create(arr); // detects long[] and returns PrimativeList<Long>
System.out.println(list.get(1)); // prints: 2
list.set(2, 15);
System.out.println(arr[2]); // prints: 15
여기에서 얻으십시오 : https://github.com/Sf298/Sauds-Toolbox/blob/master/src/main/java/PrimitiveArrayWrapper/PrimitiveList.java
참고 : 아직 완전히 테스트하지 않았으므로 버그 / 문제가 있는지 알려주십시오.