如何在Java中创建可扩展的动态数组而不使用预制类?

4

嗯,这是一道作业问题,所以拜托了,请给我码字吧! :)

无论如何,这是我的要求:
我需要有一个类,其中包含另一个类对象的数组属性。在我看来,正确的方法是使用LinkedList、Vector或类似的东西。不幸的是,上次我这样做时,我的教授非常生气,因为他认为我在没有理解基本知识的情况下使用了高级的东西。

现在,下一个明显的解决方案是创建具有固定元素数量的数组,并添加检查获取和设置的内容,以查看数组是否已满。如果已满,它们将创建新的更大的数组,将旧数组的数据复制到新数组并将新数组返回给调用者。如果大部分为空,它们将创建新的较小数组,并将数据从旧数组移动到新数组。在我看来,这看起来有点愚蠢。对于我的家庭作业,可能不会有超过3个元素的数组,但我希望制定可扩展的解决方案,而不是手动计算关于数组填充频率、平均新元素添加数量的统计数据,然后使用计算结果来计算新数组中的元素数量等等。

顺便说一句,没有必要从数组中间删除元素。

有什么提示吗?


1
在使用预构建的LinkedList等高级结构之前,我们必须自己完成这项工作(调整数组大小)!是的,这可能看起来很愚蠢,但一旦你做到了,你就会更好地理解“高级东西”在底层是如何工作的。现在,先不要考虑统计数据,保持简单!祝你好运! :) - FrustratedWithFormsDesigner
1
事实上,问题是我知道如何做所有那些事情。以前我们有一门C语言课程,其中我们必须(除其他事项外)动态地为从终端读取的字符串中的每个字符分配空间(没有缓冲区!)。我只是想问是否有其他花哨的方法可以在Java中完成此操作,我可能已经忽略了。无论如何,感谢您的评论。 - AndrejaKo
6个回答

6
class test {
    private Object[] objects;
    private int size;

    public test() {
        objects = new Object[10];
        size = 0;
    }

    public void push(Object o) {
        if (objects.length == size) {
            throw new RuntimeException("This wouldn't happen if I didn't have to reinvent the wheel");
        }
        objects[size] = o;
        size++;
    }

    public Object pop() {
        size--;
        Object o = objects[size];
        objects[size] = null;
        return o;
    }
}

开个玩笑,我认为最好的方法是实现自己的链表,然后在你的类中使用它。类似这样:

class Element {
    Object val;
    Element next;
    Element prev;

    public Element(Object val, Element next, Element prev) {
        this.val = val;
        this.next = next;
        this.prev = prev;
    }

}

class LinkedList {
    Element head;
    Element tail;

    public void add(Object o) {
        Element el = new Element(o, null, tail);
        tail.next = el;
    }

    public Object remove() {
        Element o = tail;
        tail = o.prev;
        tail.next = null;
        return o.val;
    }
}

谢谢您打出如此有趣的帖子,它确实让我的一天变得更好了!我会再考虑一下这个问题,但我可能会使用类似的东西。 - AndrejaKo

4

您需要做的一件事是在需要扩大数组大小时创建一个比旧数组大两倍的数组。同样,如果需要缩小数组大小,请在数组半满时才执行。

这将使您需要进行更少的数组复制。

这样做将需要保持一个变量来跟踪数组的实际大小,因为数组的长度将无法准确表示实际大小。


好主意,因为我不指望数组长度会有足够的变化来证明更复杂的计算。 - AndrejaKo
1
“2”只是一个普通的因子,但当前尺寸的任何倍数在统计上都具有相同的影响。 - Joachim Sauer

3

如果要将一个已有的数组复制到一个更小或更大的数组中,您可能会发现System#arrayCopy()很有用。

以下是启动示例:

Object[] originalArray = new Object[3];
// ...
Object[] resizedArray = new Object[originalArray.length + 2]; // Grow with 2.
System.arrayCopy(originalArray, 0, resizedArray, 0, originalArray.length);

这将会把整个originalArray的项目复制到resizedArray的开头。在resizedArray末尾的2个槽位仍然是null,所以你可以用它来存储其他项目。
这应该能让您开始了。祝好运 :)

2
或者你可以写成 oldArray = Arrays.copyOf(oldArray, oldArray.length * 2 + 1); 这样也可以实现相同的效果。 - helpermethod

1

这是数据结构课吗?听起来你的教授希望你实现自己的链表数据结构或类似的东西,而不是使用Java提供的。Google和你的教材是你的好朋友。


不,这不是数据结构课,这是Java和C#课。实际上,如果没有指针,你会如何制作传统的链表呢?可以使用某种包装类,该类将具有对该类对象的两个引用以及对数据类的引用,还有一些其他类将链接包装器类? - AndrejaKo
使用引用并让垃圾回收机制负责清理。示例请参见此处:http://www.java-tips.org/java-se-tips/java.lang/linked-list-implementation-in-java.html - sjobe

1
如果我没记错的话,ArrayList类的工作方式是通过具有固定大小的数组(初始容量为您设置的任何值),当它已满时会以您描述的方式调整大小。
您可以使用链表,但听起来您的教授希望您自己编写程序,所以创建自己的类来展示您知道它如何工作?

实际上,我现在正在做的作业重点是AWT。其中一个要求是拥有一个类,该类将扩展Canvass并包含另一个类的可变数量的对象,该类将扩展Frame(如果我正确理解了设置)。 - AndrejaKo

-1

我认为这是一种非常简单的方法 :p,这是我们无法在C中实现但可以在Java中实现的。

package javaapplication21;

import java.util.Scanner;
public class JavaApplication21 {
    public static void main(String[] args) {
       int a;
       Scanner obj=new Scanner(System.in);
       System.out.print("Enter array size=");
       a=obj.nextInt();
       int b[]=new int[a];
       for(int i=0;i<b.length;i++){
          System.out.println(b[i]+i);
       }
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接