IT TIP

Java에서 현재 요소를 유지하면서 배열 크기를 조정합니까?

itqueen 2020. 12. 28. 22:21
반응형

Java에서 현재 요소를 유지하면서 배열 크기를 조정합니까?


Java에서 배열 크기를 조정하는 방법을 찾았지만 현재 요소를 유지하면서 배열 크기를 조정하는 방법을 찾을 수 없습니다 .

같은 예제 코드를 찾았 int[] newImage = new int[newWidth];지만 이전에 저장된 요소를 삭제합니다.

내 코드는 기본적으로 이렇게 할 것입니다. 새 요소가 추가 될 때마다 배열이 1 만큼 커집니다 . 동적 프로그래밍으로이 작업을 수행 할 수 있다고 생각하지만 구현 방법을 잘 모르겠습니다.


Java에서는 배열의 크기를 조정할 수 없습니다. 다음 중 하나가 필요합니다.

  1. 원하는 크기의 새 배열을 만들고 다음을 사용하여 원래 배열의 내용을 새 배열로 복사합니다. java.lang.System.arraycopy(...);

  2. java.util.ArrayList<T>배열을 더 크게 만들어야 할 때이 작업을 수행 하는 클래스를 사용하십시오 . 질문에서 설명하는 내용을 멋지게 요약합니다.

  3. java.util.Arrays.copyOf(...)원래 배열의 내용으로 더 큰 배열을 반환하는 메서드를 사용하십시오 .


좋지는 않지만 작동합니다.

    int[] a = {1, 2, 3};
    // make a one bigger
    a = Arrays.copyOf(a, a.length + 1);
    for (int i : a)
        System.out.println(i);

앞서 언급했듯이 ArrayList 로 이동하십시오.


여기에 몇 가지 방법이 있습니다.


방법 1 : System.arraycopy():

지정된 위치에서 시작하여 지정된 소스 배열의 배열을 대상 배열의 지정된 위치로 복사합니다. 배열 구성 요소의 하위 시퀀스는 src에서 참조하는 소스 배열에서 dest에서 참조하는 대상 배열로 복사됩니다. 복사 된 구성 요소의 수는 길이 인수와 같습니다. 소스 배열의 srcPos ~ srcPos + length-1 위치의 구성 요소는 대상 배열의 destPos ~ destPos + length-1 위치에 각각 복사됩니다.

Object[] originalArray = new Object[5];   
Object[] largerArray = new Object[10];
System.arraycopy(originalArray, 0, largerArray, 0, originalArray.length);

방법 2 : Arrays.copyOf():

지정된 배열을 복사하고 필요한 경우 널 (NULL)로 자르거나 패딩하여 복사본이 지정된 길이를 갖도록합니다. 원본 배열과 복사본 모두에서 유효한 모든 인덱스의 경우 두 배열에 동일한 값이 포함됩니다. 복사본에서는 유효하지만 원본이 아닌 인덱스의 경우 복사본에는 null이 포함됩니다. 이러한 인덱스는 지정된 길이가 원래 배열의 길이보다 큰 경우에만 존재합니다. 결과 배열은 원래 배열과 정확히 동일한 클래스입니다.

Object[] originalArray = new Object[5];   
Object[] largerArray = Arrays.copyOf(originalArray, 10);

이 방법은 일반적으로 System.arraycopy() 배후에서 사용합니다 .


방법 3 : ArrayList:

List 인터페이스의 크기 조정 가능 배열 구현. 모든 선택적 목록 작업을 구현하고 null을 포함한 모든 요소를 ​​허용합니다. List 인터페이스를 구현하는 것 외에도이 클래스는 목록을 저장하기 위해 내부적으로 사용되는 배열의 크기를 조작하는 메서드를 제공합니다. (이 클래스는 비 동기화된다는 점을 제외하면 Vector와 거의 동일합니다.)

ArrayList는 포함 할 수있는 것보다 더 많은 요소를 추가하면 자동으로 확장된다는 점을 제외하면 배열과 유사하게 작동합니다. 그것은 것 배열에 연동 하고, 용도는 Arrays.copyOf .

ArrayList<Object> list = new ArrayList<>();

// This will add the element, resizing the ArrayList if necessary.
list.add(new Object());

당신은 당신을 ArrayList위해 일하는 것을 사용할 수 있습니다.


배열 대신 ArrayList를 사용할 수 있습니다. n 개의 요소를 추가 할 수 있도록

 List<Integer> myVar = new ArrayList<Integer>();

표준 클래스 java.util.ArrayList는 크기 조정이 가능한 배열이며 새 요소가 추가되면 커집니다.


어레이 크기는 변경할 수 없습니다. 그러나 더 큰 배열을 만들어 한 배열의 요소를 다른 배열로 복사 할 수 있습니다.

Array가 가득 찬 경우 두 배 크기의 Array를 만들고 Array가 절반이 찬 경우 Array를 절반으로 줄이는 것이 좋습니다.

public class ResizingArrayStack1 {
    private String[] s;
    private int size = 0;
    private int index = 0;

    public void ResizingArrayStack1(int size) {
        this.size = size;
        s = new String[size];
    }


    public void push(String element) {
        if (index == s.length) {
            resize(2 * s.length);
        }
        s[index] = element;
        index++;
    }

    private void resize(int capacity) {
        String[] copy = new String[capacity];
        for (int i = 0; i < s.length; i++) {
            copy[i] = s[i];
            s = copy;
        }
    }

    public static void main(String[] args) {
        ResizingArrayStack1 rs = new ResizingArrayStack1();
        rs.push("a");
        rs.push("b");
        rs.push("c");
        rs.push("d");
    }
}

배열의 크기를 조정할 수는 없지만 이전 값을 유지하거나 java.util.List를 사용하여 재정의 할 수 있습니다.

다음은 두 가지 솔루션을 따르지만 아래 코드를 실행하는 성능 차이를 포착하십시오.

자바 목록은 450 배 빠르지 만 메모리는 20 배 더 무겁습니다!

testAddByteToArray1 nanoAvg : 970355051 memAvg : 100000
testAddByteToList1 nanoAvg : 1923106 memAvg : 2026856
testAddByteToArray1 nanoAvg : 919582271 memAvg : 100000
testAddByteToList1 nanoAvg : 1922660 memAvg : 2026856
testAddByteToArray1 nanoAvg : 917727475 memAvg : 100000
testAddByteToList1 nanoAvg : 1904896 memAvg : 2026856
testAddByteToArray1 nanoAvg : 918483397 memAvg : 100000
testAddByteToList1 nanoAvg : 1907243 memAvg : 2026856
import java.util.ArrayList;
import java.util.List;

public class Test {

    public static byte[] byteArray = new byte[0];
    public static List<Byte> byteList = new ArrayList<>();
    public static List<Double> nanoAvg = new ArrayList<>();
    public static List<Double> memAvg = new ArrayList<>();

    public static void addByteToArray1() {
        // >>> SOLUTION ONE <<<
        byte[] a = new byte[byteArray.length + 1];
        System.arraycopy(byteArray, 0, a, 0, byteArray.length);
        byteArray = a;
        //byteArray = Arrays.copyOf(byteArray, byteArray.length + 1); // the same as System.arraycopy()
    }

    public static void addByteToList1() {
        // >>> SOLUTION TWO <<<
        byteList.add(new Byte((byte) 0));
    }

    public static void testAddByteToList1() throws InterruptedException {
        System.gc();
        long m1 = getMemory();
        long n1 = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            addByteToList1();
        }
        long n2 = System.nanoTime();
        System.gc();
        long m2 = getMemory();
        byteList = new ArrayList<>();
        nanoAvg.add(new Double(n2 - n1));
        memAvg.add(new Double(m2 - m1));
    }

    public static void testAddByteToArray1() throws InterruptedException {
        System.gc();
        long m1 = getMemory();
        long n1 = System.nanoTime();
        for (int i = 0; i < 100000; i++) {
            addByteToArray1();
        }
        long n2 = System.nanoTime();
        System.gc();
        long m2 = getMemory();
        byteArray = new byte[0];
        nanoAvg.add(new Double(n2 - n1));
        memAvg.add(new Double(m2 - m1));
    }

    public static void resetMem() {
        nanoAvg = new ArrayList<>();
        memAvg = new ArrayList<>();
    }

    public static Double getAvg(List<Double> dl) {
        double max = Collections.max(dl);
        double min = Collections.min(dl);
        double avg = 0;
        boolean found = false;
        for (Double aDouble : dl) {
            if (aDouble < max && aDouble > min) {
                if (avg == 0) {
                    avg = aDouble;
                } else {
                    avg = (avg + aDouble) / 2d;
                }
                found = true;
            }
        }
        if (!found) {
            return getPopularElement(dl);
        }
        return avg;
    }

    public static double getPopularElement(List<Double> a) {
        int count = 1, tempCount;
        double popular = a.get(0);
        double temp = 0;
        for (int i = 0; i < (a.size() - 1); i++) {
            temp = a.get(i);
            tempCount = 0;
            for (int j = 1; j < a.size(); j++) {
                if (temp == a.get(j))
                    tempCount++;
            }
            if (tempCount > count) {
                popular = temp;
                count = tempCount;
            }
        }
        return popular;
    }

    public static void testCompare() throws InterruptedException {
        for (int j = 0; j < 4; j++) {
            for (int i = 0; i < 20; i++) {
                testAddByteToArray1();
            }
            System.out.println("testAddByteToArray1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\tmemAvg:" + getAvg(memAvg).longValue());
            resetMem();
            for (int i = 0; i < 20; i++) {
                testAddByteToList1();
            }
            System.out.println("testAddByteToList1\tnanoAvg:" + getAvg(nanoAvg).longValue() + "\t\tmemAvg:" + getAvg(memAvg).longValue());
            resetMem();
        }
    }

    private static long getMemory() {
        Runtime runtime = Runtime.getRuntime();
        return runtime.totalMemory() - runtime.freeMemory();
    }

    public static void main(String[] args) throws InterruptedException {
        testCompare();
    }
}

배열의 크기를 조정할 수 없습니다. 그러나 원래 배열을 새로 크기가 지정된 배열로 복사하고 현재 요소를 유지하여 배열의 크기를 변경할 수 있습니다. 요소를 제거하고 크기를 조정하여 배열의 크기를 줄일 수도 있습니다.

import java.util.Arrays 
public class ResizingArray {

    public static void main(String[] args) {

        String[] stringArray = new String[2] //A string array with 2 strings 
        stringArray[0] = "string1";
        stringArray[1] = "string2";

        // increase size and add string to array by copying to a temporary array
        String[] tempStringArray = Arrays.copyOf(stringArray, stringArray.length + 1);
        // Add in the new string 
        tempStringArray[2] = "string3";
        // Copy temp array to original array
        stringArray = tempStringArray;

       // decrease size by removing certain string from array (string1 for example)
       for(int i = 0; i < stringArray.length; i++) {
           if(stringArray[i] == string1) {
               stringArray[i] = stringArray[stringArray.length - 1];
               // This replaces the string to be removed with the last string in the array
               // When the array is resized by -1, The last string is removed 
               // Which is why we copied the last string to the position of the string we wanted to remove
               String[] tempStringArray2 = Arrays.copyOf(arrayString, arrayString.length - 1);
                // Set the original array to the new array
               stringArray = tempStringArray2;
           }
       }
    }    
}

일부 클래스 내에서 아래 솔루션을 시도해 볼 수 있습니다.

int[] a = {10, 20, 30, 40, 50, 61};

// private visibility - or change it as needed
private void resizeArray(int newLength) {
    a = Arrays.copyOf(a, a.length + newLength);
    System.out.println("New length: " + a.length);
}

죄송합니다. 현재로서는 배열 크기를 조정할 수 없으며 절대 없을 수도 있습니다.

그래서 제 권장 사항 은 프로세스의 시작부터 필요한 배열의 크기를 얻을 수있는 솔루션을 찾기 위해 더 많이 생각 하는 것입니다. 이것은 종종 코드를 실행하는 데 조금 더 많은 시간 (라인)이 필요하지만 많은 메모리 리소스를 절약 할 수 있음을 의미합니다.

ReferenceURL : https://stackoverflow.com/questions/13197702/resize-an-array-while-keeping-current-elements-in-java

반응형