source

원시 길이 배열을 긴 길이 목록으로 변환

factcode 2022. 9. 11. 17:09
반응형

원시 길이 배열을 긴 길이 목록으로 변환

헤드데스크에 대한 질문은 조금 쉬울 수 있지만, 첫 번째 시도는 전혀 성공하지 못했습니다.저는 일련의 원시적인 롱을 목록으로 만들고 싶었고, 이렇게 하려고 했습니다.

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

Apache Commons lang Array Utils(Java Doc, 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);

EDIT: 코멘트 및 기타 수정에 따라 목록으로 완전히 변환되도록 업데이트되었습니다.

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

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

Hallidavejpalecek은 올바른 아이디어를 가지고 있습니다.어레이에 대해서 반복하고 있습니다만, 이 두 제품은, 다음의 기능을 이용하지 않습니다.ArrayList: 이 경우 리스트의 사이즈는 이미 알고 있기 때문에 작성 시 지정해야 합니다.ArrayList.

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

이렇게 하면 불필요한 어레이는 생성되지 않고ArrayList왜냐하면 그것들은 너무 짧은 것으로 판명되었고, 빈 "빈"은 낭비되지 않기 때문이다.ArrayList공간 요건을 과대평가했습니다.물론 목록에 요소를 계속 추가할 경우 새 백업 배열이 필요합니다.

좀 더 상세하게 설명하지만, 이것은 효과가 있습니다.

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

이 예에서는 Arrays.asList()가 입력을 Longs 목록이 아닌 Long[] 배열 목록으로 해석하고 있는 것으로 보입니다.확실히 좀 놀랍네요.이 경우 오토박스는 원하는 대로 작동하지 않습니다.

하나의 가능성으로, Guava 라이브러리는 다른 원시 유형에 대한 유사한 유틸리티 클래스와 함께 이 기능을 제공합니다.

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

: ,, 음 음 음 다 음 음 but but but but but but but but but but but but but but but but but but but 。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> lst = new ArrayList<Long>();

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

Java 8의 또 다른 방법

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

저는 다음과 같은 문제를 해결하기 위해 작은 라이브러리를 쓰고 있습니다.

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

만약 당신이 신경 쓴다면, 여기를 체크하세요.

Java 8의 또 다른 방법

final long[] a = new long[]{1L, 2L};
final List<Long> l = Arrays.stream(a).boxed().collect(Collectors.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,, 고, 고, 고, 고, 또, implement, ation, ation, ation, (, (, (, ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', ', , then, then, ', 'List(스루(스루)AbstractList 거의 합니다.Arrays.asList 및 , , 、 , 、 자 、 box 、 box 、 box 、 box box ,box , , , , , , , , , , 。

transform을 사용할 수 있습니다.

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

스태틱 Import를 사용하여 포함하면 다음과 같이 사용할 수 있습니다.

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

새 목록을 만들고 모든 값을 추가할 수 있지만(루프 또는 스트림에 사용) 매우 큰 어레이에서 작업하여 성능이 저하되었습니다.그래서 사용하기 쉬운 나만의 원시 배열 래퍼 클래스를 만들었습니다.

예:

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

메모: 아직 충분히 테스트하지 않았기 때문에 버그나 문제가 발견되면 알려주세요.

하시면 됩니다.LongStream 때문에

List<Long> longs = LongStream.of(new long[]{1L, 2L, 3L}).boxed()
                             .collect(Collectors.toList());

언급URL : https://stackoverflow.com/questions/754294/convert-an-array-of-primitive-longs-into-a-list-of-longs

반응형