在 Java 中保持当前元素的同时调整数组的大小?

我已经在 Java 中找到了一种调整数组大小的方法,但是我找不到调整数组 同时保留当前元素大小的方法。

我找到了类似于 int[] newImage = new int[newWidth];的示例代码,但是这会删除之前存储的元素。

我的代码基本上是这样做的: 每当添加一个新元素,数组就会扩大 1。我认为动态编程可以做到这一点,但我不确定如何实现它。

287539 次浏览

你可以只使用 ArrayList为你做这项工作。

您可以使用数组列表而不是数组。这样您就可以添加 n 个元素

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

标准类 java.util.ArrayList 是可调整大小的数组,在添加新元素时会增大。

你不能在 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);

如前所述,使用 数组列表

这里有一些方法可以做到这一点。


方法1: System.arraycopy():

将数组从指定的源数组(从指定位置开始)复制到目标数组的指定位置。数组组件的子序列从 src 引用的源数组复制到 dest引用的目标数组。复制的组件数等于长度参数。将源数组中位于 srcPos 通过 srcPos + length-1的组件分别通过目标数组的 destPos + length-1复制到目标数组中的位置 destPos。

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

方法二: Arrays.copyOf():

复制指定的数组,使用空值(如果需要)截断或填充,以便复制具有指定的长度。对于在原始数组和副本中都有效的所有索引,这两个数组将包含相同的值。对于在副本中有效但不是原始索引的任何索引,副本将包含 null。当且仅当指定的长度大于原始数组的长度时,才会存在此类索引。结果数组与原始数组属于完全相同的类。

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

注意,此方法通常使用 System.arraycopy() 在幕后


方法3: ArrayList:

List 接口的可调整数组实现。实现所有可选的列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口之外,该类还提供了一些方法来操作内部用于存储列表的数组的大小。(这个类大致相当于 Vector,只是它是非同步的。)

ArrayList 函数类似于数组,只不过当添加的元素超出数组所能包含的数量时,它会自动展开。是 由数组支持使用 Arrays.copy

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


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

不可能调整数组的大小。但是,可以通过将原始数组复制到新的数组并保留当前元素来更改数组的大小。还可以通过删除元素和调整大小来减小数组的大小。

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

您不能调整数组的大小,但是您可以使用旧值或 java.util.List 重新定义它

下面是两个解决方案,但是要捕捉运行下面代码时的性能差异

Java 列表的速度是其他列表的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();
}
}

无法更改数组大小。 但是您可以通过创建一个更大的 Array 来将一个数组的元素复制到另一个数组中。

如果 Array 已满,建议创建双倍大小的 Array,如果 Array 已满,建议将 Reduce 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");
}
}

你可以在一些类中尝试下面的解决方案:

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

对不起,但此时不可能调整数组的大小,而且可能永远都不会被调整。

因此,我的建议是 多想想找到一个解决方案,允许您从过程的开始就获得所需的数组的大小。这通常意味着您的代码需要更多的时间(行)来运行,但是您将节省大量的内存资源。

我们不能使用数组数据类型,而是使用一个可生长的数组,它在 Java 中是 arrayList。