기본 long 배열을 Long 목록으로 변환


138

이것은 다소 쉬운 헤드 데스크 문제 일 수 있지만 첫 번째 시도는 놀랍게도 완전히 실패했습니다. 나는 원시적 인 long 배열을 가져 와서 목록으로 바꾸고 싶었습니다.

long[] input = someAPI.getSomeLongs();
List<Long> inputAsList = Arrays.asList(input); //Total failure to even compile!

이것을하는 올바른 방법은 무엇입니까?


6
우리는 정수에 대해 같은 질문을했다고 생각합니다.
Tom Hawtin-tackline

3
@Tom

답변:


115

아파치 커먼즈 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);

편집 : 의견 및 기타 수정 사항에서 제안한대로 목록으로 완전히 변환되도록 업데이트되었습니다.


3
이것이 List 가 아니라 Longs 배열 을 생성한다는 것을 고려할 때 OP의 질문에 대답하지 않고 다운 투표를받습니다. 도대체 어떻게 56 upvotes와 탐낼 "확인"을 얻었습니까 ???
user949300

7
사람들은 Arrays.asList(ArrayUtils.toObject(input))아마 쉽게 할 수 있기 때문 입니다.
Eran Medan

@ user949300에 동의합니다. 이것은 질문에 대답하지 않습니다.
dev4life 2016 년

1
이 답변은 목록으로 완전히 변환되도록 업데이트해야합니다. 그러나 솔루션을 향한 효율적인 단계입니다.
Jim Jeffers

2
@JimJeffers-감사합니다. 완전한 변환을 포함하도록 업데이트되었습니다. 영업 이익이 포함되어 있기 때문에 List<Long> = Arrays.asList(inputBoxed)자신의 질문에 나는 그것이 명백했다 생각으로 그것을 반복 중복 발견, 내가 ... 내가 잘못 생각
에 란 메단

114

Java 8부터는 다음과 같은 스트림을 사용할 수 있습니다.

long[] arr = {1,2,3,4};
List<Long> list = Arrays.stream(arr).boxed().collect(Collectors.toList());

7
좋은 것! 불행하게도, 다소 신비스럽게도이 stream함수는 int[], long[]및에 대해서만 정의됩니다 double[].
Norswap

1
또는을 사용할 수 있습니다 LongStream.of(arr).boxed()....
aioobe

2
Arrays.stream(arr).boxed().collect(Collectors.toList());불행하게도 이것은 단지 반환 할 수 있습니다List<Object>
Senthilkumar Annadurai

간단한 작업을위한 부피가 큰 라이브러리가없고 루프도 없습니다. 좋은 대답입니다.
Alex Quilliam 1

37
import java.util.Arrays;
import org.apache.commons.lang.ArrayUtils;

List<Long> longs = Arrays.asList(ArrayUtils.toObject(new long[] {1,2,3,4}));

5
이것이하는 일과 이것이 타사 라이브러리인지에 대한 설명이 도움이 될 것입니다.
IgorGanapolsky

35

hallidavejpalecek 은 배열에 대해 올바른 아이디어를 가지고 있지만 다음과 같은 기능을 활용하지 않습니다 ArrayList. 이 경우 목록의 크기가 알려져 있으므로를 만들 때 지정해야합니다 ArrayList.

List<Long> list = new ArrayList<Long>(input.length);
for (long n : input)
  list.add(n);

이런 식으로 불필요한 배열은 ArrayList너무 짧아서 버릴 수 있도록 만들어 지지 않으며 ArrayList공간 요구 사항을 과대 평가하여 빈 "슬롯"이 낭비되지 않습니다 . 물론 목록에 요소를 계속 추가하면 새로운 백업 배열이 필요합니다.


1
코드가 성능 핫스팟의 일부로 입증되거나 배열이 매우 클 것으로 예상되지 않는 한 길이 사양을 생략하는 경향이 있습니다. 길이를 생략하면 코드를 약간 더 읽기 쉽다고 생각합니다.
hallidave

19

조금 더 장황하지만 작동합니다.

    List<Long> list = new ArrayList<Long>();
    for (long value : input) {
        list.add(value);
    }

귀하의 예에서 Arrays.asList ()는 입력을 Long 목록 대신 long [] 배열 목록으로 해석하는 것으로 보입니다. 확실히 조금 놀랍습니다. 이 경우 오토 박싱은 원하는 방식으로 작동하지 않습니다.



7

아니요, 기본 유형의 배열에서 박스형 참조 유형의 배열로 자동 변환되지 않습니다. 당신은 할 수만 있습니다

long[] input = someAPI.getSomeLongs();
List<Long> lst = new ArrayList<Long>();

for(long l : input) lst.add(l);

7

이 질문은 배열을 목록으로 바꾸는 방법에 대해 물었습니다. 지금까지 대부분의 답변 은 배열과 동일한 내용을 사용하거나 타사 라이브러리를 참조하여 목록 을 만드는 방법을 보여주었습니다 . 그러나 이러한 종류의 변환에는 간단한 기본 제공 옵션이 있습니다. 그들 중 일부는 이미 다른 답변 (예 : 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

6

Java 8의 또 다른 방법.

long[] input = someAPI.getSomeLongs();
LongStream.of(input).boxed().collect(Collectors.toList()));

6

이 문제에 대한 작은 라이브러리를 작성 중입니다.

long[] input = someAPI.getSomeLongs();
List<Long> = $(input).toList();

당신이 걱정하는 경우 여기를 확인 하십시오 .


좋은 도서관! 처음에, 나는 그것이 Java인지 확신하지 못했습니다 ... 나는 JQuery 스타일을 좋아합니다
Yanick Rochon

4

Java 8의 또 다른 방법 .

final long[] a = new long[]{1L, 2L};
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.toList());

1
목록을 반환 할 때 (할당하지 않은 경우) 다음을 수행해야합니다.Arrays.stream(a).boxed().collect(Collectors.<Long>toList());
Jon

1
이것은 기존 답변 과 동일합니다 .
Pang

3

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);
            }
        };
    }

2

비슷한 의미를 원한다면 (아마도를 통해 Arrays.asList) 고객 구현을 작성하거나 다른 사람의 고객 구현을 사용해야 합니다. 상자 및 상자의 값만 동일한 구현을 가져야 합니다.ListAbstractListArrays.asList


2

변형 을 사용할 수 있습니다 :

Transmorph transmorph = new Transmorph(new DefaultConverters());
List<Long> = transmorph.convert(new long[] {1,2,3,4}, new TypeReference<List<Long>>() {});

예를 들어 source가 int 배열 인 경우에도 작동합니다.


2

나는이 질문이 충분히 오래되었다는 것을 알고 있지만 ... 자신 만의 변환 방법을 작성할 수도 있습니다.

@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);

2
에 대하여 : catch (ArrayIndexOutOfBoundsException ex) { /* Finished getting array elements */ }당신은 끔찍한 사람입니다.
Brandon Yarbrough

이봐, 고마워! 당신의 아이러니 한 말은 Array.getLength ()를 통해 배열의 길이를 얻는 더 나은 해결책을 찾았습니다.
Pavel Netesa

1
환상적인! 나는 냉담한 태도가 일반적인 나쁜 감정 대신 진전을 이끈 것을 기쁘게 생각합니다. :) 실제로, 매우 특이한 조건을 제외하고 예외를 사용하는 것은 좋지 않습니다. 놀랍게도 제작 비용이 많이 듭니다. 이 새로운 버전은 훨씬 더 빠릅니다.
Brandon Yarbrough

1

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

참고 : 아직 완전히 테스트하지 않았으므로 버그 / 문제가 있는지 알려주십시오.


0

당신은 LongStream그것을 위해 사용할 수 있습니다

List<Long> longs = LongStream.of(new long[]{1L, 2L, 3L}).boxed()
                             .collect(Collectors.toList());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.