【问题标题】:Trouble with converting ordered int array to ordered array list将有序 int 数组转换为有序数组列表的问题
【发布时间】:2016-09-10 01:28:58
【问题描述】:

我的教授给了我们这段代码,它创建了一个排序的 int 数组,并希望我们将它转​​换为一个带有字符串的排序数组列表。这是一项维护任务,必须反映原始代码。因此,我不能使用 size 方法、Collections.sort() 或任何不反映原始代码的方法。

我们得到了

    OrderedIntList() {
    a = new int[10];
}

    public void insert(int v) {
    if(c == 0) {
        a[0]= v;
        c++;
    } else {
        int j = 0;
        for (int i = 0; i < c; i++, j++) {
            if(v < a[i]) 
                break;
        }
        for (int i = c; i > j; i--) {
            a[i] = a[i - 1];
        }

        a[j]= v; 
        c++;
    }
}

这是我想出的将其转换为数组列表的方法

        stringList() {
    list = new ArrayList<String>(10);
}

    public void insert(String element) {
    if(c == 0) {
        list.add(0, element);
        c++;
    } else {
        int j = 0;
        for (int i = 0; i < c; i++, j++) {
            if(element.compareTo(list.get(i)) == -1) 
                break;
        }
        for (int i = c; i > j; i--) {
            list.set(i, list.get(0));
        }

        list.set(j, element);
        c++;
    }
}

它不断抛出异常

list.set(i, list.get(0));

调试时我看到 ArrayList.class 抛出异常,因为索引等于大小。我似乎无法提出解决方案。任何帮助将不胜感激。

【问题讨论】:

  • 简短回答:您需要使用add 方法来增加列表的大小。您不能仅通过在尚未插入的元素上调用 set 来做到这一点。
  • @David Wallace 所说的,即使 set 确实允许这样做,你的行 list.set(i, list.get(0));与 a[i] = a[i - 1] 不同,您正在执行类似 a[i] = a[0] 的操作。所以你有两个错误。另外我只是猜测您误解了什么 list = new ArrayList(10);确实,在这种情况下,它不会列出 10 个字符串,它只是使用数字 10 作为“提示”将初始容量(不是大小)设置为 10
  • @ben 这不是“提示”。是实际大小。根据javadoc构造一个具有指定初始容量的空列表
  • 嗨@Bohemian,你说得对,容量是内存中列表的“大小”。当我说大小时,我的意思是列表的“size()”,它是列表中实际元素的数量。如果您认为容量是列表中实际元素的数量,那您就错了。
  • @ben 啊,对。容量!= 大小。

标签: java maintenance


【解决方案1】:

这个赋值的一个有趣的方面是数组和列表在行为上有很大的不同:数组有一个固定的大小,而列表随着项目的添加而扩展。对于列表,将项目添加到末尾以外的任何位置都是插入,它会自动将项目向右移动以腾出空间。数组不会发生这种情况,因此需要在您正在重构的代码中手动完成。

因此,在我看来,将数组最小化重构为列表的正确方法是将set 转换为insert,然后删除过去需要移动元素的代码。列表不再需要它:

public void insert(String element) {
    if (c == 0) {
        list.add(element);
        c++;
    } else {
        int j = 0;
        for (int i = 0; i < c; i++, j++) {
            if (element.compareTo(list.get(i)) < 0 ) 
                break;
        }
        list.insert(j, element);
        c++;
    }
}

对于列表,添加到空列表中与在位置 0 处插入是一样的,因此完全不需要对空列表进行特殊处理。但这可能不是“反映原始”代码。

另一个更细微的区别是,如果插入超过 10 个项目,此代码不会导致错误。要正确反映初始代码的行为,您需要为此专门添加一个测试。

if (c == MAX_SIZE)
    throw new ArrayIndexOutOfBoundsException(c);

很可能您的任务并不期望您处理这种情况,但值得知道的是,如果不包含重构,它会改变函数的行为。

【讨论】:

  • @Bohemian 这个答案怎么不相关?相反,arraylist 确实有足够的容量来容纳所有元素 - 但尽管事实如此,这个答案仍然成立。
【解决方案2】:

解决您的问题的一种方法是

stringList() {
  list = new ArrayList<String>(10);
}

stringList() {
  list = new ArrayList<String>(10);
  for(int i = 0; i < 10; i++){
      list.add("");
  }
}

因为只有这样才能实现包含 10 个字符串的列表,所以第一个只是创建一个能够容纳 10 个字符串的列表(这更像是一个性能提示)

【讨论】:

  • @Bohemian,你是对的,因为不需要最初填充数据结构。但是,我提出的改变是正确的。我相信您的意思是提出一种不预填充数据结构并在插入期间将元素添加到列表尾部的替代方法,而不是使用 set()。这会起作用,因为这是插入排序,但是我建议的也应该起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 2020-10-26
  • 2022-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多