如何在数组中间添加?

时间:2019-02-18 22:15:08

标签: java arrays

我正在尝试创建一个名为insertAt的方法,该方法需要3个参数(int索引,int n,int值),以便在调用时: 在[12,42,8,8,934]数组上的list.insertAt(2,4,98),它现在应该存储[12,42,98,98,98,98,8,934]。

int索引是我开始放置值的地方

int n是多少个值

int值是我要输入的实际值或数字。

我正在一个名为ArrayIntList的类中使用此方法:

public class ArrayIntList {
    private int[] elementData; // list of integers
    private int size;          // current # of elements in the list 
}

我尝试过使用下面的方法,但是我仍然坚持我所缺少的东西。如果你们能帮助我,我将不胜感激!

public void insertAt(int index, int n, int value) {
    if (index < 0 || index > size || n < 0) {
        throw new IllegalArgumentException();
    }
    size = size + n;
    for (int i = 0; i < n; i++) {
        elementData[(size - 1) - i] = elementData[(size - n) + i];
        elementData[n + i] = value;
    }
}

4 个答案:

答案 0 :(得分:4)

示例中的数组仅包含4个值,但是您尝试添加4个附加值。这是不可能的,因为数组具有固定的长度。因此,您必须创建一个长度为size + n的新数组:

int[] newElements = new int[size + n];

然后,您必须将所有从0index的元素和index直到size的元素从旧复制到新数组:

System.arraycopy(elementData, 0, newElements, 0, index);
System.arraycopy(elementData, index, newElements, index + n, size - index);

然后,您必须将新元素n次插入数组:

Arrays.fill(newElements, index, index + n, value);

最后,您必须将新数组重新分配给旧实例之一并设置新大小:

elementData = newElements;
size += n;

我从JDK使用了一些辅助方法,例如System.arraycopy,它具有以下签名:

void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

它将元素从srcsrcPossrcPos+lengthdestdestPos的{​​{1}}复制

destPost+length还是一个不错的帮手,带有以下签名:

Array.fill

它使用值void fill(int[] a, int fromIndex, int toIndex, int val) 将数组afromIndex填充到toIndex

答案 1 :(得分:2)

Answer by Lino是正确的。此外,对于这种工作,您可能应该使用除简单数组以外的其他数据结构。

如果需要更大的灵活性,请使用Java Collections framework

List

List接口按顺序跟踪元素。

Java集合仅存储对象,而不存储基元。因此,我们必须使用包装器类。在您的情况下,请使用Integer而不是int。在大多数情况下,Java的自动装箱功能将处理

ArrayList

List的一种实现是ArrayList。此类由一个简单的数组支持。因此,将中间插入会产生Lino所描述的rigamarole。但是,至少该类正在执行该工作,并且与您或我正在编写的代码不同,这些代码已经过全面测试。

List< Integer > integers = new ArrayList<>() ;
integers.add( 7 ) ;   // Add first element to the empty list.
integers.add( 42 ) ;  // Append to the end of the list.
integers.add( 1 , Integer.valueOf( 1999 ) ) ;   // Insert in the middle. Using zero-based index counting. So `1` means the second item.
integers.

或者在实践中,我将使用序数2,并将索引号减去1。

integers.add( 2-1 , Integer.valueOf( 1999 ) ) ; // Insert. Do math to convert from ordinal number (2, the second position) to index number (1).

LinkedList⬅快得多!

更好的方法是使用实​​现List的{​​{3}}类。如果数组在内存中将项目连续地打包在一起,则LinkedList的项目分别在内存中浮动,每个项目都跟踪连续项目的存储位置。

因此,插入中间的费用便宜很多:只需更改前一个项目,使其指向新项目,而新项目则指向后续项目。无需重建列表或四处移动物品。

通过调用linked list插入LinkedList,其中索引是从零开始的位置计数器,而element是您要插入的对象。

请注意List上的LinkedList::add( index , element)方法。您生成多个数字的方法可以产生一个列表,然后将该列表插入目标列表。使用这种单插入方法比多次插入要快得多,因为将链接列表遍历到 find 会花费很多。

// Make a list of values to be inserted into the main list.
int count = 3 ; 
List< Integer > inserts = new ArrayList<>( count );
for (int i = 0; i < count; i++) {
    inserts.add( 98 ) ;
}
// Insert into main list.
integers.add( 2-1 , inserts ) ;  // Do math to convert from ordinal number (2, the second position) to index number (1).

如何选择哪个List

  • 如果要通过其位置编号进行大量遍历或跳转到列表中的特定元素,请使用ArrayList。由于元素是连续的,因此按位置跳转非常便宜。
  • 如果要进行大量插入或删除操作,请使用LinkedList。由于这些元素是先后绑定在一起的,因此插入/删除仅影响一个元素,因此非常便宜。

还有许多其他List可用的实现,其中一些实现与Java捆绑在一起,而其他的则可以从第三方获得。通常,ArrayListLinkedList是主要力量,大多数人在大多数工作中都会使用。

答案 2 :(得分:1)

您需要一个数组副本,在索引插入之前复制第一个元素,添加N次新元素并添加最后一个元素

public void insertAt(int index, int n, int value) {
if (index < 0 || index > size || n < 0) {
    throw new IllegalArgumentException();
}
size = size + n;

int[] elementDataTemp = new int[elementData.length + n];

// copy first elements
for (int i = 0; i < index; i++) {
    elementDataTemp[i] = elementData[i];
}

// add new elements
for (int i = 0; i < n; i++) {
    elementDataTemp[index + i] = value;
}

// copy last elements
for (int i = index; i < elementData.length; i++) {
    elementDataTemp[ n + i ] = elementData[i];
}

// save temp array
elementData = elementDataTemp;
}

答案 3 :(得分:-1)

您可以通过多种方式执行此操作:

  1. 将元素n- array向上移位一个
  2. 在N中插入新元素