Java 链表对象的substring()方法

Java 链表对象的substring()方法,java,linked-list,substring,Java,Linked List,Substring,为我正在构建的名为LString的类编写substring()方法时遇到一些问题。此类创建一个名为LString的链表对象,用于构建字符串。它模仿Java中的String和StringBuilder对象 子字符串(int-start,int-end)从start提供的索引到end创建一个新的LString。它返回类型LString 以下是未进行任何编辑的错误消息end包括: Running substring tests (63 tests) Starting tests: ......E...

为我正在构建的名为
LString
的类编写
substring()
方法时遇到一些问题。此类创建一个名为
LString
的链表对象,用于构建字符串。它模仿Java中的
String
StringBuilder
对象

子字符串(int-start,int-end)
start
提供的索引到
end
创建一个新的
LString
。它返回类型
LString

以下是未进行任何编辑的错误消息
end
包括:

Running substring tests (63 tests)
Starting tests: ......E........................................................
Time: 0.031

There was 1 failure:
1) test43cSubStringOneChar(LStringTest$LStringSubStringTestSpecial)
java.lang.AssertionError: Substring of One Character LString is not equals LString expected: LString<a> but was: LString<a>
        at org.junit.Assert.fail(Assert.java:88)
        at org.junit.Assert.failNotEquals(Assert.java:743)
        at org.junit.Assert.assertEquals(Assert.java:118)
        at LStringTest$LStringSubStringTestSpecial.test43cSubStringOneChar(LStringTest.java:401)
        ... 10 more

Test Failed! (1 of 63 tests failed.)

Test failures: abandoning other phases.
以下是代码的相关差异,只有
substring()
不同:

public LString  substring(int start,    int end)    {
  if (start < 0 || end >= this.length() || start > end) {
     throw new IndexOutOfBoundsException();
  }
  LString substring = new LString();
  /*if (start == end) {
     return substring;
  }*/
  node node = this.front;
  for (int i = 0; i < start; i++) {
     node = node.next;
  }
  node copy = new node(node.data);
  substring.front = copy;
  for (int i = start; i < end; i++) {
     node = node.next;
     copy = copy.next = new node(node.data);
  }
  return substring;      
}

我没有检查所有的代码,只是为
substring()
方法添加了逻辑。由于您可以通过在给定位置设置一些字符来变异
LString
,因此我假设您确实需要子字符串的链接列表副本:您不希望出现这样的行为,即获取子字符串、修改父字符串并修改子字符串

您可以实现一个“聪明”的实现,在必要时才真正复制节点。例如,您可以让子字符串观察父字符串中可能影响子字符串节点的任何修改。当有一个时,就会发生复制。请参见实现此功能的模式。在您的情况下,如果只保留一个类,
LString
它将同时实现
Observer
observeable

无论如何,这里是简单的复制实现

public LString  substring(int start,    int end)    {
    if (start < 0 || end > this.length() || start > end) {
        throw new IndexOutOfBoundsException();
    }
    if (start == end) {
        return new LString(); // return an "empty" LString
    }

    // Find starting node
    Node currentNode = front;
    for (int i = 0; i < start; i++) {
        currentNode = currentNode.next;
    }

    // create new LString and copy each node from start to end
    LString ls = new LString();
    ls.front = new node(currentNode.data)
    node newCur = ls.front;
    for (int i = start+1; i<end; i++) {
        currentNode = currentNode.next;
        node newNext = new node(currentNode.data);
        newCur.next = newNext;
        newCur = newNext;
    }
    ls.size = end-start;
    return ls;
}
public-LString子字符串(int-start,int-end){
如果(开始<0 | |结束>此.length()| |开始>结束){
抛出新的IndexOutOfBoundsException();
}
如果(开始==结束){
return new LString();//返回一个“空”LString
}
//查找起始节点
节点当前节点=前端;
对于(int i=0;i对于(inti=start+1;i另一个答案中的代码没有编译,即使编译了,也不能正常运行

假设您使用的是标准的(针对Java)零基索引,并且
end
索引是独占的,那么这段代码将编译并测试

public LString substring(int start, int end) {
    if (start < 0 || end > length() || start > end) {
        throw new IndexOutOfBoundsException();
    }
    LString result = new LString();
    if (start == end) {
        return result;
    }
    node node = this.front;
    for (int i = 0; i < start; i++) {
        node = node.next;
    }
    node copy = new node(node.data);
    result.front = copy;
    for (int i = start + 1; i < end; i++) {
        node = node.next;
        copy = copy.next = new node(node.data);
    }
    result.size = end - start;
    return result;
}

谢谢,这帮了大忙。现在我只想把它复制到一个新的LString中。我还需要编写其他方法。快速提问,在这个实现中,我收到一个一个字符的LString子字符串的错误,在这个例子中是“a”,错误消息是“AssertionError”,你知道为什么吗?我现在什么都看不到。对不起,我实际上是在没有编译的情况下写的,还有一些细节需要更正(比如
大小
for
int
的声明)……好吧,另一个解决方案显然已经调试了我的;)感谢您的回复,如果end是inclusive,我会怎么做?不客气。关于
end
inclusive,这对于Java来说不是常规的。而且您永远不会得到空的子字符串,因为,例如,
substring(3,3)
将返回第四个字符,但是
子字符串(3,2)
将无效。但要使其具有包容性,您必须更改两件事:1)方法开头的guard子句必须说
end>=length()
而不是
end>length()
,以及2)循环的最后一个
将初始化
inti=start
而不是
inti=start+1
。更正,必须更改end的三项内容:3)如果(start==end){return substring;},则删除第二个保护子句
if(start==end){return substring;}
。另请参阅我的更新答案。再次感谢。如果你不介意继续,你会给我很大帮助。我进行了编辑,包括第三次编辑,但收到的错误比我原来的错误多。它似乎添加了超出需要的错误。对你的问题进行编辑,将新代码包含在单独的部分中,我会查看。t测试肯定会以独占方式结束。我需要查看方法LStringTest$LStringSubStringTestSpecial.test43cSubStringOneChar()的代码。请在问题中包含该代码。我为所有SubStringOneChar()添加了代码方法equals方法中存在错误。看看你是否能找出equals返回字符串长度为1的错误答案的原因。好吧,我想我知道问题所在。在substring方法末尾的
return
语句之前添加一行
substring.size=end-start;
。我更新了我的答案来显示这一点。啊,是的!我是关于更改大小的问题。谢谢您的帮助。我现在将转到替换方法
   @Test public void test43aSubStringOneChar() {
         LString testLString = new LString("a");
         assertEquals("Substring of One Character LString is not Empty",
               nullLString, testLString.substring(0, 0));
      }

      @Test public void test43bSubStringOneChar() {
         LString testLString = new LString("a");
         assertEquals("Substring of One Character LString is not Empty",
               nullLString, testLString.substring(1, 1));
      }

      @Test public void test43cSubStringOneChar() {
         LString testLString = new LString("a");
         assertEquals("Substring of One Character LString is not equals LString",
               testLString, testLString.substring(0, 1));
      }
public LString  substring(int start,    int end)    {
    if (start < 0 || end > this.length() || start > end) {
        throw new IndexOutOfBoundsException();
    }
    if (start == end) {
        return new LString(); // return an "empty" LString
    }

    // Find starting node
    Node currentNode = front;
    for (int i = 0; i < start; i++) {
        currentNode = currentNode.next;
    }

    // create new LString and copy each node from start to end
    LString ls = new LString();
    ls.front = new node(currentNode.data)
    node newCur = ls.front;
    for (int i = start+1; i<end; i++) {
        currentNode = currentNode.next;
        node newNext = new node(currentNode.data);
        newCur.next = newNext;
        newCur = newNext;
    }
    ls.size = end-start;
    return ls;
}
public LString substring(int start, int end) {
    if (start < 0 || end > length() || start > end) {
        throw new IndexOutOfBoundsException();
    }
    LString result = new LString();
    if (start == end) {
        return result;
    }
    node node = this.front;
    for (int i = 0; i < start; i++) {
        node = node.next;
    }
    node copy = new node(node.data);
    result.front = copy;
    for (int i = start + 1; i < end; i++) {
        node = node.next;
        copy = copy.next = new node(node.data);
    }
    result.size = end - start;
    return result;
}
@Override
public String toString() {
    if (this.front == null) return "";
    StringBuilder sb = new StringBuilder(length());
    node node = this.front;
    do sb.append(node.data);
    while ((node = node.next) != null);
    return sb.toString();
}