14

在 Java 中做一个可调整大小的数组的最佳方法是什么?我尝试使用 Vector,但是当你进行插入时,所有元素都会转移,我需要一个可以增长但元素保持原位的数组。我确信对此有一个简单的答案,但我仍然不太确定。

4

9 回答 9

24

作为替代方案,您可以使用ArrayList。它是 List 接口的可调整大小的数组实现。

用法(使用字符串):

List<String> myList = new ArrayList<String>();
myList.add("a");
myList.add("c");
myList.add("b");

顺序就像你把它们放进去一样:a、c、b。

您还可以获得这样的单个项目:

String myString = myList.get(0);

这将为您提供第 0 个元素:“a”。

于 2010-04-06T00:38:31.070 回答
5

就像三条指出的那样:“ An array is a static datastructure, so they can't grow”。列表接口可以由数组支持(例如Kevin 在他的帖子中指出的ArrayList)。当列表结构已满并且必须将新项目添加到列表中时。然后该结构首先创建一个新数组,该数组可以包含旧元素以及必须添加到列表中的新元素。

列表接口有不同的实现,它们都有优点/缺点,你应该选择最能解决你的问题集的一个。下面我将尝试简要总结何时使用哪种实现:

不是线程安全的实现:

  • ArrayList : List 接口的 Resizable-array 实现。size, isEmpty, get, set, iterator, and listIterator当您在恒定时间内执行大量操作时,您应该使用此实现。该add操作在摊销常数时间内运行,即添加 n 个元素需要 O(n) 时间。我认为您应该在进行更多查找(get())然后将项目添加到列表(add())时使用此实现。
  • LinkedList:此实现不是由数组备份,而是将节点“链接”在一起。在我看来,当你做更多的时候,你应该使用这个add()实现get()

线程安全的实现:

请注意,这些列表实现不是线程安全的,这意味着在从多个线程访问它们时可能会出现竞争条件。如果您想使用来自多个线程的 List 实现,我建议您研究java.util.concurrent包并使用该类的实现。

于 2010-04-06T01:17:58.580 回答
3

出于其他答案中解释的原因,您可能应该使用 ArrayList 而不是 Vector。

然而 ...

我尝试使用 Vector,但是当你进行插入时,所有元素都会转移,我需要一个可以增长但元素保持原位的数组。

当您执行 时insertElementAt(pos, elem),您已明确要求进行元素转换。如果你不希望元素被移动,你应该使用set(pos, elem)。或者如果你想在向量的末尾添加元素,你也可以使用add(elem).

顺便说一句,上一段适用于所有的实现,List而不仅仅是.VectorList

于 2010-04-06T04:34:48.727 回答
1

我尝试使用 Vector,但是当你进行插入时,所有元素都会转移,我需要一个可以增长但元素保持原位的数组。

您可能想使用 ArrayList 而不是 Vector。

它们都提供了大致相同的接口,您可以通过调用set(idx, element). 这不会做任何转移。但是,它也不允许您扩大数组:您只能在已经占用的位置(不能超出数组的当前大小)插入,以便在您必须使用的末尾添加新元素add(element)

ArrayList 和 Vector 之间的区别在于 Vector 具有您很可能不需要的同步代码,这使得 ArrayList 更快一些。

于 2010-04-06T00:49:51.737 回答
1

ArrayList 和 LinkedList

空间复杂度:

a) ArrayList:在初始化时分配一块内存,并在动态添加元素时每次达到最大大小时加倍。

b) LinkedList:它只在每次将项目添加到列表时分配内存。

运行时复杂性:

a) ArrayList:与链表相比,查找更快,插入和删除更慢

b) LinkedList:相比数组列表,插入和删除更快,搜索更慢

于 2013-12-11T02:08:39.620 回答
1

如果要在所有元素都已插入或删除后操作数组数据,有一种方法是尝试创建一个LinkedList或ArrayList,只需调整大小,数据输入完成后,可以将ArrayList转为Array,然后做所有你平时对 Array 做的事情。

于 2010-04-06T01:56:03.193 回答
1

数组不能在 Java 中动态调整大小。对此的解决方案是使用 ArrayList 或创建另一个临时数组然后分配它。

您可以找到有关 ArrayList 的教程,但如果您只想在 Java 中自定义 ResizableArray。就是这样。但不建议使用!它只是一个 FAKE 可调整大小的数组,当您创建太多对象时,堆内存会增加。这只是向您展示这个想法。

  • 界面
public interface Resizable<T> {

    void add(T data);
    int delete(int index);
    int size();
    void print();
}
  • 实现类
public class ResizeableImpl<T> implements Resizable<T> {

    private Object[] temp = null;
    private Object[] originals = new Object[0];

    @Override
    public void add(T data) {
        Object[] temp = new Object[originals.length+1];
        for (int i=0; i<originals.length; i++) {
            temp[i]=originals[i];
        }
        temp[originals.length]=data;
        originals=temp;
    }

    @Override
    public int delete(int index) {
        int success=0;
        switch (originals.length) {
            case 0: //No Data to delete
                success=0;
                break;
            case 1: //One Data is delete and so no data, too!
                originals = new Object[0];
                success = 1;
                break;
            default: //>=2
                int count=0;
                originals[index]=null;
                temp = new Object[originals.length-1];
                for (int i=0; i<originals.length; i++) {
                    if (originals[i]!=null)
                    temp[count++]=originals[i];
                }
                originals = temp;
                success = 1;
        }

        return success;
    }

    @Override
    public int size() {
        return originals.length;
    }

    @Override
    public void print() {
        StringBuilder sb = null;

        if (originals.length==0) {
            System.out.println("No data available!");
            return;
        }

        for (int i=0; i<originals.length; i++) {
            if (sb==null) {
                sb = new StringBuilder();
                sb.append(originals[i]);
            }
            else {
                sb.append(", "+originals[i]);
            }
        }
        sb.append(".");
        System.out.println(sb.toString());
    }
}
  • 主要方法
public class App {

    public static void main(String[] args) {
        //Program to interfaces, not implementations
        Resizable<Integer> obj = new ResizeableImpl<>();

        obj.add(13);
        obj.add(20);
        obj.add(17);
        obj.add(25);
        obj.add(100);
        obj.add(12);
        obj.print();

        int result = obj.delete(2); //This will delete 17.
        if (result==1) {
            System.out.println("Deletion is successful!");
        }
        obj.print();

        obj.delete(3); //This will delete 100.
        obj.print();
    }
}

输出

13, 20, 17, 25, 100, 12.
Deletion is successful!
13, 20, 25, 100, 12.
13, 20, 25, 12.
于 2020-07-11T15:11:14.287 回答
0

使用 ArrayList 或 LinkedList。

于 2012-11-07T14:26:51.567 回答
-2

在 Collections 框架中使用精彩的类比使用数组更好。但是,如果您的问题是从“测验”的角度提出的,那么您应该这样做。创建您自己的调整大小方法,例如:

  int[] oldArray = {1,2,3};

  int oldSize = java.lang.reflect.Array.getLength(oldArray);
  Class elementType = oldArray.getClass().getComponentType();
  Object newArray = java.lang.reflect.Array.newInstance(
         elementType,newSize);
  int preserveLength = Math.min(oldSize,newSize);
  if (preserveLength > 0)
      System.arraycopy (oldArray,0,newArray,0,preserveLength);

  oldArray = newArray;
于 2010-04-06T00:55:54.877 回答