Подтвердить что ты не робот

Как увеличить длину массива

У меня есть быстрый вопрос. У меня есть целочисленный массив в java, который нуждается в его длине, чтобы варьироваться по всему классу. В частности, мне нужно, чтобы он увеличивался на один в определенных ситуациях. Я попробовал это так.

        sbgHeadX = new int[ numberOfSBG ];

Я бы увеличил целочисленную переменную numberOfSBG, когда мне это нужно, но я не думаю, что это работает. Есть ли другой способ?

4b9b3361

Ответ 1

Я предлагаю вам использовать ArrayList, так как вам больше не придется беспокоиться о длине. После создания невозможно изменить размер массива:

Массив - это объект-контейнер, который содержит фиксированное число значений одного типа. Длина массива устанавливается при создании массива. После создания его длина фиксирована.

(Источник)

Ответ 2

Если вы не хотите или не можете использовать ArrayList, тогда есть метод утилиты:

Arrays.copyOf() 

который позволит вам указать новый размер, сохраняя при этом элементы.

Ответ 3

Массивы в Java имеют фиксированный размер, указанный при объявлении. Чтобы увеличить размер массива, вам нужно создать новый массив большего размера и скопировать все старые значения в новый массив.

Пример:

char[] copyFrom  = { 'a', 'b', 'c', 'd', 'e' };
char[] copyTo    = new char[7];

System.out.println(Arrays.toString(copyFrom));
System.arraycopy(copyFrom, 0, copyTo, 0, copyFrom.length);
System.out.println(Arrays.toString(copyTo));

В качестве альтернативы вы можете использовать динамическую структуру данных, такую ​​как List.

Ответ 4

По определению массивы фиксированного размера. Вместо этого вы можете использовать Arraylist, который является массивом "динамического размера". На самом деле происходит то, что виртуальная машина "регулирует размер" * массива, открытый в ArrayList.

См. также

* с использованием обратных копий

Ответ 5

Вы можете использовать ArrayList. Массив имеет фиксированное количество размеров.

Этот Пример здесь может вам помочь. Пример довольно прост с его выходом.

Output:
2 5 1 23 14 
New length: 20
Element at Index 5:29
List size: 6
Removing element at index 2: 1
2 5 23 14 29

Ответ 6

Перво-наперво:

  • В Java после создания массива его длина фиксируется. Массивы не могут быть изменены.
  • Вы можете скопировать элементы массива в новый массив с другим размером. Самый простой способ сделать это - использовать один из методов Arrays.copyOf().
  • Если вам нужна коллекция переменного размера, вам, вероятно, лучше использовать ArrayList вместо массива.

При этом могут быть ситуации, когда у вас нет другого выбора, кроме как изменить размер массива, созданного где-то за пределами вашего кода. 1 Единственный способ сделать это - манипулировать сгенерированным байт-кодом кода, который создает массив.

Проверка концепции

Ниже приведен небольшой проект для проверки концепции, который использует инструментарий Java для динамического изменения размера массива 2. Пример проекта представляет собой проект Maven со следующей структурой:

.
├─ pom.xml
└─ src
   └─ main
      └─ java
         └─ com
            └─ stackoverflow
               └─ agent
                  ├─ Agent.java
                  └─ test
                     └─ Main.java

Main.java

Этот файл содержит целевой класс, которым мы собираемся манипулировать байт-кодом:

package com.stackoverflow.agent.test;

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] array = {"Zero"};

        fun(array);

        System.out.println(Arrays.toString(array));
    }

    public static void fun(String[] array) {
        array[1] = "One";
        array[2] = "Two";
        array[3] = "Three";
        array[4] = "Four";
    }
}

В методе main мы создаем массив String размером 1. В методе fun 4 дополнительных значения назначаются вне границ массива. Запуск этого кода как есть, очевидно, приведет к ошибке.

Agent.java

Этот файл содержит класс, который будет выполнять манипуляции с байт-кодом:

package com.stackoverflow.agent;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class Agent {
    public static void premain(String args, Instrumentation instrumentation) {
        instrumentation.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader l, String name, Class<?> c,
                    ProtectionDomain d, byte[] b) {

                if (name.equals("com/stackoverflow/agent/test/Main")) {
                    byte iconst1 = (byte) 0x04;
                    byte iconst5 = (byte) 0x08;
                    byte anewarray = (byte) 0xbd;

                    for (int i = 0; i <= b.length - 1; i++) {
                        if (b[i] == iconst1 && b[i + 1] == anewarray) {
                            b[i] = iconst5;
                        }
                    }

                    return b;
                }

                return null;
            }
        });
    }
}

На уровне байт-кода создание массива String в классе Main состоит из двух команд:

  • iconst_1, который iconst_1 константу int со значением 1 в стек (0x04).
  • anewarray, который извлекает значение стека и создает эталонный массив 3 того же размера (0xbd). Приведенный выше код ищет эту комбинацию команд в классе Main и, если она найдена, заменяет команду const_1 команду const_5 (0x08), эффективно изменяя размеры массива до 5. 4

pom.xml

POM файл maven используется для создания JAR-приложения и настройки основного класса и класса агента Java. 5

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.stackoverflow</groupId>
  <artifactId>agent</artifactId>
  <version>1.0-SNAPSHOT</version>

  <build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.1.1</version>
        <configuration>
          <archive>
            <manifestEntries>
              <Main-Class>com.stackoverflow.agent.test.Main</Main-Class>
              <Premain-Class>com.stackoverflow.agent.Agent</Premain-Class>
              <Agent-Class>com.stackoverflow.agent.Agent</Agent-Class>
              <Can-Retransform-Classes>true</Can-Retransform-Classes>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Построить и выполнить

Пример проекта может быть собран с помощью стандартной команды mvn clean package.

Выполнение без ссылки на код агента приведет к ожидаемой ошибке:

$> java -jar target/agent.jar 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
        at com.stackoverflow.agent.test.Main.fun(Main.java:15)
        at com.stackoverflow.agent.test.Main.main(Main.java:9)

При выполнении с кодом агента получится:

$> java -javaagent:target/agent.jar -jar target/agent.jar
[Zero, One, Two, Three, Four]

Это показывает, что размер массива был успешно изменен с помощью манипулирования байт-кодом.


1 Такие ситуации возникали в вопросах здесь и здесь, последняя из которых побудила меня написать этот ответ.
2 Технически пример проекта не меняет размер массива.Он просто создает его с размером, отличным от указанного в коде.Фактически изменение размера существующего массива с сохранением его ссылки и копированием его элементов было бы немного сложнее.
3 Для примитивного массива соответствующей операцией байт-кода будет вместо этого newarray (0xbc).
4 Как уже отмечалось, это всего лишь доказательство концепции (и очень хакерской).Вместо случайной замены байтов, более надежная реализация могла бы использовать библиотеку манипулирования байт-кодом, такую как ASM, чтобы вставить команду pop за которой sipush команда sipush перед любой newarray или anewarray.Еще несколько советов по этому решению можно найти в комментариях к этому ответу.
5 В реальном сценарии код агента, очевидно, будет находиться в отдельном проекте.

Ответ 7

Item[] newItemList = new  Item[itemList.length+1];
    //for loop to go thorough the list one by one
    for(int i=0; i< itemList.length;i++){
        //value is stored here in the new list from the old one
        newItemList[i]=itemList[i];
    }
    //all the values of the itemLists are stored in a bigger array named newItemList
    itemList=newItemList;

Ответ 8

Пример метода изменения длины массива (со старым копированием данных):

static int[] arrayLengthChange(int[] arr, int newLength) {
    int[] arrNew = new int[newLength];
    System.arraycopy(arr, 0, arrNew, 0, arr.length);
    return arrNew;
}