插入方法作为数组的一部分
Insert Method as part of an Array
这个方法已经困扰我好几个小时了。它是 X 类型 array
的一部分,应该采用任何数据类型。这是我第一次使用泛型 array
和调试器。
我在测试中遇到的错误是:
expected: 'hello' but was 'null' and
0: ...ArrayOutOfBoundsException: 0
看起来 ArrayOutOfBoundsException
处理也没有正确抛出。
我不知道该怎么办。我的删除功能似乎工作正常。
public void insert( int index, X item )
{
if ( index > 0 || index < length )
{
length++;
X[] obj2 = (X[]) new Object[obj.length - 1];
for ( int i = 0; i == index; i++ )
{
obj2[i] = obj[i];
}
obj2[index] = item;
for ( int i = index; i == length; i++ )
{
obj2[i + 1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
@Test
public void testInsert()
{
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
b.insert(1, "adios");
assertEquals("hello", b.get(0));
assertEquals("adios", b.get(1));
assertEquals("bye", b.get(2));
assertEquals(3, b.size());
b.insert(1, "buenos dias");
assertEquals(4, b.size());
assertEquals("hello", b.get(0));
assertEquals("buenos dias", b.get(1));
assertEquals("adios", b.get(2));
b.insert(0, "hi");
assertEquals(5, b.size());
assertEquals("hi", b.get(0));
assertEquals("hello", b.get(1));
b.insert(4, "see ya");
assertEquals(6, b.size());
assertEquals("see ya", b.get(4));
assertEquals("bye", b.get(5));
}
首先,您的边界检查逻辑不正确。 index
的每个可能值都大于 0
或 小于 length
。这会导致您尝试创建的 ArrayIndexOutOfBoundsException
不被抛出。 (如果您确实越界访问数组,Java 可能会抛出自己的 AIOOBE。)
您应该确保满足这两个条件。使用 &&
而不是 ||
.
if ( index > 0 && index < length )
此外,在将旧元素复制到新数组时,您需要意识到 for
循环条件为 true
意味着 "keep going",而不是 "stop"。在 index
尚未达到 length
时继续循环。将 ==
更改为 <
.
for ( int i = 0; i < index; i++ )
(另一个 for
循环需要进行类似的更改。)
你有一些问题。
1)假设length
是一个实例变量,它反映了obj
数组的length
,那么你实际上要进行如下测试:
if (index >= 0 && index <= length)
这会测试您的 new 项目索引是否为 0 或更多,或者是否比当前 obj
数组中的最大索引大 1(即,等于当前数组长度)。 这确实略微取决于您的预期合同我认为您可以 "insert" 在列表末尾是合理的,但您可能必须将其限制为仅插入中间,因此只有在有另一个元素的情况下。在这种情况下,您需要
if (length > 0 && index >= 0 && index < length)
注意:您测试 &&
,而不是 ||
,因为您需要所有条件都为真。如果你想在开始时做一个更标准的参数有效性检查,你可以这样做:
if (index < 0 || index > length)
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
这样做的好处是不需要 else
块并略微减少代码嵌套。
2) 然后你递增 this.length
,然后你递增 new Object[obj.length - 1];
,这是没有意义的。我怀疑你想做:
length++;
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[this.length];
或更好:
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
3) 你的第一个循环执行 for ( int i = 0; i == index; i++ )
,应该是:
for (int i = 0; i < index; i++)
这是因为循环条件语句不测试突破条件(即当条件为真时停止)而是测试继续条件(即在 i
小于 index
时继续)
4) 你的第二个循环执行 for ( int i = index; i == length; i++ )
,并且应该执行:
for (int i = index; i < length - 1; i++)
这是因为你的长度增加了,但你使用 i
来引用原始数组索引,而不是更大的数组索引。
总而言之,我认为它看起来像下面的代码。
这里最大的问题可能是您的测试方法。您在一个大型测试中有多个测试。这不会帮助您隔离各个错误并在不中断调试器的情况下找出您的方法有什么问题(双关语不是故意的,但我只是看到它所以我会离开它)。理想情况下,如果您的单元测试很小、集中且孤立,则不必使用调试器。此类测试的示例包含在末尾。
class XArray<X> {
private int length;
private X[] obj;
public XArray() {
this.obj = initBackingArray(0);
this.length = 0;
}
private X[] initBackingArray(int length) {
@SuppressWarnings("unchecked")
X[] result = (X[])new Object[length];
return result;
}
public X get(int index) {
return this.obj[index];
}
public int size() {
return this.length;
}
public void add(X item) {
insert(length, item);
}
public void insert( int index, X item )
{
if (index >= 0 && index <= length)
{
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
for (int i = 0; i < index; i++)
{
obj2[i] = obj[i];
}
obj2[index] = item;
for (int i = index; i < length - 1; i++)
{
obj2[i+1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
}
示例测试:
@Test
public void testAddOnceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
}
@Test
public void testAddTwiceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
}
@Test
public void testInsertOnEmptyWorks() {
XArray<String> b = new XArray<String>();
b.insert(0, "hello");
}
@Test
public void testAddOnceInsertBeforeWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.insert(0, "hello");
}
这个方法已经困扰我好几个小时了。它是 X 类型 array
的一部分,应该采用任何数据类型。这是我第一次使用泛型 array
和调试器。
我在测试中遇到的错误是:
expected: 'hello' but was 'null' and
0: ...ArrayOutOfBoundsException: 0
看起来 ArrayOutOfBoundsException
处理也没有正确抛出。
我不知道该怎么办。我的删除功能似乎工作正常。
public void insert( int index, X item )
{
if ( index > 0 || index < length )
{
length++;
X[] obj2 = (X[]) new Object[obj.length - 1];
for ( int i = 0; i == index; i++ )
{
obj2[i] = obj[i];
}
obj2[index] = item;
for ( int i = index; i == length; i++ )
{
obj2[i + 1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
@Test
public void testInsert()
{
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
b.insert(1, "adios");
assertEquals("hello", b.get(0));
assertEquals("adios", b.get(1));
assertEquals("bye", b.get(2));
assertEquals(3, b.size());
b.insert(1, "buenos dias");
assertEquals(4, b.size());
assertEquals("hello", b.get(0));
assertEquals("buenos dias", b.get(1));
assertEquals("adios", b.get(2));
b.insert(0, "hi");
assertEquals(5, b.size());
assertEquals("hi", b.get(0));
assertEquals("hello", b.get(1));
b.insert(4, "see ya");
assertEquals(6, b.size());
assertEquals("see ya", b.get(4));
assertEquals("bye", b.get(5));
}
首先,您的边界检查逻辑不正确。 index
的每个可能值都大于 0
或 小于 length
。这会导致您尝试创建的 ArrayIndexOutOfBoundsException
不被抛出。 (如果您确实越界访问数组,Java 可能会抛出自己的 AIOOBE。)
您应该确保满足这两个条件。使用 &&
而不是 ||
.
if ( index > 0 && index < length )
此外,在将旧元素复制到新数组时,您需要意识到 for
循环条件为 true
意味着 "keep going",而不是 "stop"。在 index
尚未达到 length
时继续循环。将 ==
更改为 <
.
for ( int i = 0; i < index; i++ )
(另一个 for
循环需要进行类似的更改。)
你有一些问题。
1)假设length
是一个实例变量,它反映了obj
数组的length
,那么你实际上要进行如下测试:
if (index >= 0 && index <= length)
这会测试您的 new 项目索引是否为 0 或更多,或者是否比当前 obj
数组中的最大索引大 1(即,等于当前数组长度)。 这确实略微取决于您的预期合同我认为您可以 "insert" 在列表末尾是合理的,但您可能必须将其限制为仅插入中间,因此只有在有另一个元素的情况下。在这种情况下,您需要
if (length > 0 && index >= 0 && index < length)
注意:您测试 &&
,而不是 ||
,因为您需要所有条件都为真。如果你想在开始时做一个更标准的参数有效性检查,你可以这样做:
if (index < 0 || index > length)
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
这样做的好处是不需要 else
块并略微减少代码嵌套。
2) 然后你递增 this.length
,然后你递增 new Object[obj.length - 1];
,这是没有意义的。我怀疑你想做:
length++;
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[this.length];
或更好:
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
3) 你的第一个循环执行 for ( int i = 0; i == index; i++ )
,应该是:
for (int i = 0; i < index; i++)
这是因为循环条件语句不测试突破条件(即当条件为真时停止)而是测试继续条件(即在 i
小于 index
时继续)
4) 你的第二个循环执行 for ( int i = index; i == length; i++ )
,并且应该执行:
for (int i = index; i < length - 1; i++)
这是因为你的长度增加了,但你使用 i
来引用原始数组索引,而不是更大的数组索引。
总而言之,我认为它看起来像下面的代码。
这里最大的问题可能是您的测试方法。您在一个大型测试中有多个测试。这不会帮助您隔离各个错误并在不中断调试器的情况下找出您的方法有什么问题(双关语不是故意的,但我只是看到它所以我会离开它)。理想情况下,如果您的单元测试很小、集中且孤立,则不必使用调试器。此类测试的示例包含在末尾。
class XArray<X> {
private int length;
private X[] obj;
public XArray() {
this.obj = initBackingArray(0);
this.length = 0;
}
private X[] initBackingArray(int length) {
@SuppressWarnings("unchecked")
X[] result = (X[])new Object[length];
return result;
}
public X get(int index) {
return this.obj[index];
}
public int size() {
return this.length;
}
public void add(X item) {
insert(length, item);
}
public void insert( int index, X item )
{
if (index >= 0 && index <= length)
{
@SuppressWarnings("unchecked")
X[] obj2 = (X[]) new Object[++length];
for (int i = 0; i < index; i++)
{
obj2[i] = obj[i];
}
obj2[index] = item;
for (int i = index; i < length - 1; i++)
{
obj2[i+1] = obj[i];
}
obj = obj2;
}
else
{
throw new java.lang.ArrayIndexOutOfBoundsException("" + index);
}
}
}
示例测试:
@Test
public void testAddOnceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
}
@Test
public void testAddTwiceWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.add("bye");
}
@Test
public void testInsertOnEmptyWorks() {
XArray<String> b = new XArray<String>();
b.insert(0, "hello");
}
@Test
public void testAddOnceInsertBeforeWorks() {
XArray<String> b = new XArray<String>();
b.add("hello");
b.insert(0, "hello");
}