LString class, using linked lists to make strings,

2019-03-02 14:00发布

问题:

I'm having trouble writing a compareTo() and charAt() methods for a linked list object that builds strings. The class, called LString contains a constructor and a few other methods. It runs with another file that tests its ability as a linked list string builder, and I am receiving this error message:

    Running constructor, length, toString tests (10 tests)
Starting tests: ..........
Time: 0.000
OK! (10 tests passed.)

Running compareTo and equals tests (18 tests)
Starting tests: EEEEEEEE.EEE.E....
Time: 0.016

There were 12 failures:
1) t21aTestCompareTo[0](LStringTest$LStringCompareToTest)
java.lang.AssertionError: compareTo of "abc" and "abd" wrong expected:<-1> but was:<0>
        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 org.junit.Assert.assertEquals(Assert.java:555)
        at LStringTest$LStringCompareToTest.t21aTestCompareTo(LStringTest.java:259)
        ... 9 more
2) t22aTestEquals[0](LStringTest$LStringCompareToTest)
java.lang.AssertionError: equals of "abc" and "abd" wrong expected:<false> but was:<true>
        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$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
3) t21aTestCompareTo[1](LStringTest$LStringCompareToTest)
java.lang.IndexOutOfBoundsException: bad index
        at LString.charAt(LString.java:91)
        at LString.compareTo(LString.java:64)
        at LStringTest$LStringCompareToTest.t21aTestCompareTo(LStringTest.java:259)
        ... 9 more
4) t22aTestEquals[1](LStringTest$LStringCompareToTest)
java.lang.NullPointerException
        at LString.equals(LString.java:79)
        at LStringTest$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
5) t21aTestCompareTo[2](LStringTest$LStringCompareToTest)
java.lang.IndexOutOfBoundsException: bad index
        at LString.charAt(LString.java:91)
        at LString.compareTo(LString.java:64)
        at LStringTest$LStringCompareToTest.t21aTestCompareTo(LStringTest.java:259)
        ... 9 more
6) t22aTestEquals[2](LStringTest$LStringCompareToTest)
java.lang.AssertionError: equals of "a" and "ab" wrong expected:<false> but was:<true>
        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$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
7) t21aTestCompareTo[3](LStringTest$LStringCompareToTest)
java.lang.IndexOutOfBoundsException: bad index
        at LString.charAt(LString.java:91)
        at LString.compareTo(LString.java:64)
        at LStringTest$LStringCompareToTest.t21aTestCompareTo(LStringTest.java:259)
        ... 9 more
8) t22aTestEquals[3](LStringTest$LStringCompareToTest)
java.lang.AssertionError: equals of "abc" and "abcd" wrong expected:<false> but was:<true>
        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$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
9) t22aTestEquals[4](LStringTest$LStringCompareToTest)
java.lang.AssertionError: equals of "B" and "a" wrong expected:<false> but was:<true>
        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$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
10) t21aTestCompareTo[5](LStringTest$LStringCompareToTest)
java.lang.AssertionError: compareTo of "BB" and "Ba" wrong expected:<-1> but was:<0>
        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 org.junit.Assert.assertEquals(Assert.java:555)
        at LStringTest$LStringCompareToTest.t21aTestCompareTo(LStringTest.java:259)
        ... 9 more
11) t22aTestEquals[5](LStringTest$LStringCompareToTest)
java.lang.AssertionError: equals of "BB" and "Ba" wrong expected:<false> but was:<true>
        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$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more
12) t22aTestEquals[6](LStringTest$LStringCompareToTest)
java.lang.NullPointerException
        at LString.equals(LString.java:79)
        at LStringTest$LStringCompareToTest.t22aTestEquals(LStringTest.java:269)
        ... 9 more

Test Failed! (12 of 18 tests failed.)

Test failures: abandoning other phases.

The LString class is meant to mimic Java's String and StringBuilder, but with Linked Lists instead of arrays. I'm a little confused on how to use the this keyword. Within the compareTo() method below, I imagine using this by saying to myself "if this LStrings character at this index is equal to the argument's LString character at the same index, return 0."

I'm referencing this page, but unsure how to write it efficiently: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#compareTo%28java.lang.String%29

I want compareTo() to return 0 if the LStrings have the exact same characters, a value less than zero if this LString is lexicographically less than anotherLString, and a value greater than zero if its lexicographically greater.

import java.io.*;
import java.util.*;

public class LString    {

     node   front;
     int size;

    //Creating a node class
     private    class   node {
          char data;
          node next;

          public    node (){
          }

          public    node    (char   newData){
                this.data = newData;
          }

          public    node    (char   newData,    node newNext){
                this.data = newData;
                this.next = newNext;
          }


     }
    //Constructors
     public LString(){
          this.size =   0;
          this.front =  null;
     }
     public LString(String original)    {
          this.size = original.length();
          if (original  !=  ""){

              this.front =  new node(original.charAt(0));
              node curr = this.front;

              for   (int i =1; i <  original.length(); i++) {
                    curr.next = new node(original.charAt(i));
                    curr = curr.next;
              }
          }



     }

   // Length method, returns the length of LString
     public int length()    {
        return this.size;
    }

    // compareTo method, compares this LString to anotherLString, returns 0 if equal,
   // -1 if lexicogrpahically less, and 1 if lexicographically greater
    public int compareTo(LString anotherLString)    {
      int total = 0;
      for (int i = 0; i < anotherLString.length(); i++) {
         total += this.charAt(i) - anotherLString.charAt(i);
      }
        return total;

        //}
        //return this.length()-anotherLString.length();
    }

   // a boolean equals method that returns true if LString and other are the same, false if not
    public boolean  equals(Object other)    {
        if  (other == null  ||  !(other instanceof LString)) {
            return false;
        }
        else {
            LString otherLString    = (LString)other;
         if (this.front.data == otherLString.front.data) {

               return true;
         }
        }
      return true;
    }

   // charAt returns the character of LString at the argument index
    public char charAt(int index)   {

        if ((index < 0) || (index >= this.length())) {
         throw new IndexOutOfBoundsException("bad index");
      }
      return this.front.data;
    }

The methods in question are unfinished in this code. Any advice is appreciated, trying to learn Java.

回答1:

I've slightly corrected your code.

You should define hashCode() if you define equals(). Also it's useful to implement LString as CharSequence.

public class LString implements Comparable<LString>
{
    Node front;
    int size;

    //Creating a node class
    private static class Node
    {
        char data;
        Node next;

        public Node()
        {
        }

        public Node( char newData )
        {
            this.data = newData;
        }

        public Node( char newData, Node newNext )
        {
            this.data = newData;
            this.next = newNext;
        }
    }

    //Constructors
    public LString()
    {
        this.size = 0;
        this.front = null;
    }

    public LString( String original )
    {
        this.size = original.length();
        if ( original.length() > 0 )
        {

            this.front = new Node( original.charAt( 0 ) );
            Node curr = this.front;

            for ( int i = 1; i < original.length(); i++ )
            {
                curr.next = new Node( original.charAt( i ) );
                curr = curr.next;
            }
        }
    }

    // Length method, returns the length of LString
    public int length()
    {
        return this.size;
    }

    // compareTo method, compares this LString to anotherLString, returns 0 if equal,
    // -1 if lexicogrpahically less, and 1 if lexicographically greater
    public int compareTo( LString anotherLString )
    {
        int len1 = length();
        int len2 = anotherLString.length();
        int lim = Math.min( len1, len2 );
        // char v1 = front.data;
        //   char v2 = anotherLString.front.data;
        Node cn1 = front;
        Node cn2 = anotherLString.front;

        int k = 0;
        while ( k < lim )
        {
            char c1 = cn1.data;
            char c2 = cn2.data;
            if ( c1 != c2 )
            {
                return c1 - c2;
            }
            k++;
            cn1 = cn1.next;
            cn2 = cn2.next;
        }

        return len1 - len2;
    }

    // a boolean equals method that returns true if LString and other are the same, false if not
    public boolean equals( Object other )
    {
        if ( this == other )
        {
            return true;
        }
        if ( other instanceof LString )
        {
            LString anotherLString = ( LString ) other;
            int n = length();
            if ( n == anotherLString.length() )
            {
                Node n1 = front;
                Node n2 = anotherLString.front;
                while ( n1 != null )
                {
                    if ( n1.data != n2.data )
                    {
                        return false;
                    }
                }

                return true;
            }
        }

        return false;
    }

    // charAt returns the character of LString at the argument index
    public char charAt( int index )
    {
        if ( ( index < 0 ) || ( index >= this.length() ) )
        {
            throw new IndexOutOfBoundsException( "bad index" );
        }

        Node curNode = front;
        for ( int i = 0; i < this.length(); i++, curNode = curNode.next )
        {
            if ( i == index )
            {
                return curNode.data;
            }
        }

        throw new IllegalStateException();
    }
}