In: Computer Science
can you teach me how to implement the ArrayStringList and LinkedStringList using the same interface? I've implemented a couple of methods in my ArrayStringList but I'm not sure if I'm doing it correctly and im confused on how to do the splice, reverse, and a couple others. I'm also having trouble getting started on my LinkedStringList.
In this project, you will be providing two different implementations of a StringList interface, which defines different operations that one should be able to do with a list of strings. A list is simply an object that represents an ordered collection of elements. The list implementation can decide how the elements are stored internally so long as users are able to interact with those elements via the methods defined in the interface. In this way, a list is an example of an abstract data type (ADT). To put it another way: while the implementor needs to understand the specific details of the implementation (in order to write the code to make it happen), the user of a list does not. The users simply interact with objects of the list implementation through the methods defined in the interface.
In order to truly understand this project, you must take a step back and think about how a list object and its storage are separate things. A list uses its storage to actually store its elements. For example, the size of a list does not have to be the same as the size of its storage, although the storage is likely at least as big as the list. For example, say you have created a shopping list with 5 items on it. You would say that there are five items on your list. If the list is implemented as a class in Java, you might have some internal storage (say, an array) that can hold more than five items. From the outside perspective, the list still contains 5 elements even though the internal storage may be larger. The internal array is hidden and is of no concern to the user of the class.
Each implementation of the StringList interface will be a concrete class with specific functional and non-functional requirements. These classes need to implement StringList either directly or via a common abstract parent class.
For this project, you will NOT have access to the .java files for the interface. Instead, you will have access to the generated API documentation for the interface here. Implementors should make sure that each method functions or behaves as described by the interface's API documentation, except in cases where a functional requirement changes the behavior of the method.
Implementors are always free to implement additional methods in addition to the ones defined by the interface. However, they should not assume that users (e.g., graders) will use them (even if declared with public visibility), since they are not defined in the interface. These additional methods may help avoid redundancy and promote code reuse within an implementation.
A functional requirement is added to your point total if satisfied. There will be no partial credit for any of the requirements that simply require the presence of a method related to a particular functionality. The actual functionality is tested using test cases.
For this project, you are required to create two different classes that implement the same interface. While the specific details are listed below, the following diagram illustrates the general relationship between your classes and the interface (with instance variables and most methods omitted from the diagram for brevity):
The specific requirements for each class are presented below.
ArrayStringList: Create the cs1302.list.ArrayStringList class such that it properly implements the cs1302.listadt.StringList interface with additional requirements listed below.
You must explicitly define and document default constructor for this class. The initial size of an ArrayStringList is 0 regardless of the list's underlying storage--remember, the list's internal storage and the list itself are two different things. Here is the signature:
public ArrayStringList();
You must explicitly define and document a copy constructor for this class. It should make the new list a deep copy of the other list. Therefore, the initial size and element values of the new list should be the other list. The other list can be any implementation of the StringList interface. Here is the signature:
public ArrayStringList(StringList other);
Over the lifetime of an ArrayStringList object, its internal storage may change in order to accomodate more list elements. When your code increases the size of an ArrayStringList object's internal array storage, you should actively avoid: i) increasing the array size by one; and ii) doubling the size of the array. Somewhere in between is more reasonable. Furthermore, you should not set the initial array size to 0 or to the largest number that is allowed.
There is a requirement related to this class's storage included in the Absolute Requirements section.
Extra Credit (5 points): Override the iterator() method for your ArrayStringList class as described in the StringList interface. This may require you to create an additional class that implements another interface. Some web searching might recommend an anonymous inner class. Please do not do this. If you choose to do this extra credit, then you should create a regular class that properly implements the desired interface. In addition to properly overriding iterator(), to receive points for this extra credit, you must include a file called EXTRA.md in your immediate project directory and place the text [EC2] on a single line within the file. In this file, you should have one line for each extra credit that you want the grader to check.
NOTE: You do not need to implement the iterator() method if you are not doing the extra credit.
LinkedStringList: Create the cs1302.list.LinkedStringList class such that it properly implements the cs1302.listadt.StringList interface with additional requirements listed below.
You must explicitly define and document a default constructor for this class. The initial size of a LinkedStringList is 0 regardless of the list's underlying storage--remember, the list's internal storage and the list itself are two different things. Here is the signature:
public LinkedStringList();
You must explicitly define and document a copy constructor for this class. It should make the new list a deep copy of the other list. Therefore, the initial size and element values of the new list should be the other list. The other list can be any implementation of the StringList interface. Here is the signature:
public LinkedStringList(StringList other);
There is a requirement related to this class's storage included in the Absolute Requirements section.
Extra Credit (5 points): Override the iterator() method for your LinkedStringList class as described in the StringList interface. This may require you to create an additional class that implements another interface. Some web searching might recommend an anonymous inner class. Please do not do this. If you choose to do this extra credit, then you should create a regular class that properly implements the desired interface. In addition to properly overriding iterator(), to receive points for this extra credit, you must include a file called EXTRA.md in your immediate project directory and place the text [EC2] on a single line within the file. In this file, you should have one line for each extra credit that you want the the grader to check.
Non-Functional Requirements
A non-functional requirement is subtracted from your point total if not satisfied. In order to emphasize the importance of these requirements, non-compliance results in the full point amount being subtracted from your point total. That is, they are all or nothing.
(0 points) [RECOMMENDED] No Static Variables: Use of static variables is not appropriate for this assignment. However, static constants are perfectly fine.
Modifier and Type | Method and Description |
---|---|
boolean | add(int index, String s)
Inserts the specified string at the specified position in this list. |
boolean | add(int index, StringList sl)
Inserts the strings contained in the specified list at the specified position in this list, in the order in which they appear in the specified list. |
boolean | add(String s)
Appends the specified string to the end of this list. |
boolean | add(StringList sl)
Appends the strings contained in the specified list to the end of this list, in the order in which they appear in the specified list. |
void | clear()
Removes all of the strings from this list. |
boolean | contains(String o)
Returns true if this list contains the specified string. |
boolean | containsIgnoreCase(String o)
Returns true if this list contains the specified string, ignoring case. |
boolean | containsSubstring(String o)
Returns true if any string in this list contains the specified substring. |
StringList | distinct()
Builds and returns a new StringList from this list without any duplicate strings. |
String | get(int index)
Returns the string at the specified position in this list. |
int | indexOf(String s)
Returns the index of the first occurrence of the specified string in this list, or -1 if this list does not contain the string. |
int | indexOfIgnoreCase(String s)
Returns the index of the first occurrence of the specified string, ignoring case, in this list, or -1 if this list does not contain the string. |
boolean | isEmpty()
Returns true if this list contains no elements. |
default Iterator | iterator()
Returns a new iterator over the strings in this list in proper sequence. |
default String | makeString()
Returns a string representation of this list with all of strings directly concatenated in order. |
String | makeString(String sep)
Returns a string representation of this list with every string in the sequence separated by the specified separator string. |
default String | makeString(String start, String sep, String end)
Returns a string representation of this list that begins with start and ends with end, with every string in the sequence separated by sep. |
String | remove(int index)
Removes the string at the specified position in this list. |
StringList | reverse()
Builds and returns a new StringList that contains the strings from this list in reverse order. |
String | set(int index, String s)
Replaces the string at the specified position in this list with the specified element. |
int | size()
Returns the number of elements in this list. |
StringList | splice(int fromIndex, int toIndex)
Builds and returns a new StringList that contains the strings from this list between the specified fromIndex, inclusive, and toIndex, exclusive. |
String[] | toArray()
Returns a new array containing all of the strings in this list in proper sequence (from first to last element). |
Constructor and Description |
---|
Node()
Constructs a new node with all properties unset. |
Node(String str)
Constructs a new node with the str property set and the next property unset. |
Node(String str, StringList.Node next)
Constructs a new node with the str and next properties set. |
Method Summary
Modifier and Type | Method and Description |
---|---|
StringList.Node | getNext()
Returns the value of the next property for this node. |
String | getStr()
Returns the value of the str property for this node. |
void | setNext(StringList.Node next)
Sets the value of the next property for this node. |
void | setStr(String str)
Sets the value of the str property for this node. |
Used to download the project in UNIX that includes the interface and tester:
git clone --depth 1 https://github.com/cs1302uga/cs1302-listadt.git
To be clear, both listadt.jar and bin are assumed to be in the your main project directory when the tester is run. If your code does not yet compile because one of the classes does not yet fully implement the StringList interface, then you can rapidly get it to compile by following the advice given here.
To see the options for the tester, run listadt-tester in your main project directory:
$ listadt-tester
Usage: listadt-tester [OPTION]... Run public test cases for the cs1302-listadt project. This program assumes that your code compiles correctly, the default location for compiled code is 'bin', and 'listadt.jar' is in the current directory. Options: -a | --ArrayStringList Check and test cs1302.list.ArrayStringList -l | --LinkedStringList Check and test cs1302.list.LinkedStringList --help Show this help information (ignore other options)
You can test your ArrayStringList class, LinkedStringList class, or both. For example, to just test ArrayStringList, you can run:
$ listadt-tester -a
I've implemented the program in Java-
Functional Requirements
A functional requirement is added to your point total if satisfied. There will be no partial credit for any of the requirements that simply require the presence of a method related to a particular functionality. The actual functionality is tested using test cases.
ArrayStringList
: Create the
cs1302.list.ArrayStringList
class such that it
properly implements the cs1302.listadt.StringList
interface with additional requirements listed below.
You must explicitly define and document default constructor for
this class. The initial size of an ArrayStringList
is
0
regardless of the list's underlying
storage--remember, the list's internal storage and the list itself
are two different things. Here is the signature:
public ArrayStringList();
You must explicitly define and document a copy constructor for
this class. It should make the new list a deep copy of the other
list. Therefore, the initial size and element values of the new
list should be the other list. The other list can be any
implementation of the StringList
interface. Here is
the signature:
public ArrayStringList(StringList other);
There is a requirement related to this class's storage included in the Absolute Requirements section.
Extra Credit (5 points): Override the
iterator()
method for your
ArrayStringList
class as described in the
StringList
interface. This may require you to
create an additional class that implements another interface. In
addition to properly overriding iterator()
, to receive
points for this extra credit, you must include a file called
EXTRA.md
in your immediate project directory and place
the text [EC1]
on a single line within the file. In
this file, you should have one line for each extra credit that you
want the the grader to check.
NOTE: You do not need to implement the
iterator()
method if you are not doing the extra
credit.
LinkedStringList
: Create the
cs1302.list.LinkedStringList
class such that it
properly implements the cs1302.listadt.StringList
interface with additional requirements listed below.
You must explicitly define and document default constructor for
this class. The initial size of a LinkedStringList
is
0
regardless of the list's underlying
storage--remember, the list's internal storage and the list itself
are two different things. Here is the signature:
public LinkedStringList();
You must explicitly define and document a copy constructor for
this class. It should make the new list a deep copy of the other
list. Therefore, the initial size and element values of the new
list should be the other list. The other list can be any
implementation of the StringList
interface. Here is
the signature:
public LinkedStringList(StringList other);
There is a requirement related to this class's storage included in the Absolute Requirements section.
Extra Credit (5 points): Override the
iterator()
method for your
LinkedStringList
class as described in the
StringList
interface. This may require you to
create an additional class that implements another interface. In
addition to properly overriding iterator()
, to receive
points for this extra credit, you must include a file called
EXTRA.md
in your immediate project directory and place
the text [EC2]
on a single line within the file. In
this file, you should have one line for each extra credit that you
want the the grader to check.
NOTE: You do not need to implement the
iterator()
method if you are not doing the extra
credit.
(100 points) Test Cases: The bulk of this project will be graded based on 50 JUnit test cases, each worth 2 points. This is the same as someone using the classes you wrote based purely on the interface definitions. If you implement the interface correctly, then you should pass the associated test cases.
Non-Functional Requirements
A non-functional requirement is subtracted from your point total if not satisfied. In order to emphasize the importance of these requirements, non-compliance results in the full point amount being subtracted from your point total. That is, they are all or nothing.
(25 points) Code Style Guidelines: You should be consistent with the style aspect of your code in order to promote readability. All of the individual code style guidelines listed below are part of a single non-functional requirement that, like the others, is all or nothing. Besides consistency, the following conventions will be enforced:
Reference type names are written in
UpperCamelCase. Class names are
typically nouns or noun phrases. For example,
Character
or ImmutableList
. Interface
names may also be nouns or noun phrases (for example,
List
), but may sometimes be adjectives or adjective
phrases instead (for example, Readable
).
Method names are written in
lowerCamelCase. Method names are also typically
verbs or verb phrases. For example, sendMessage
or
stop
.
Braces are always used where optional. Braces
should be used with if
, else
,
for
, do
, and while
statements, even when the body is empty or contains only a single
statement.
Block Indentation: 4 spaces. Each time a new block or block-like construct is opened, the indent increases by four spaces. When the block ends, the indent returns to the previous indent level. The indent level applies to both code and comments throughout the block.
If you use Emacs, you can add the following lines to your
~/.emacs
file to make tabs for new files
comply with this requirement:
(setq-default indent-tabs-mode nil)
(setq-default c-default-style "linux"
c-basic-offset 4)
(setq-default tab-width 4)
(setq indent-line-function 'insert-tab)
Column limit: 100. You should limit the number of characters, including whitespace, on any given line to 100 characters. Except as noted below, any line that would exceed this limit must be manually line-wrapped in a consistent manner. Exceptions to the column limit include:
package
and import
statements.If you use Emacs, then you can add the following lines to your
~/.emacs
file to highlight characters that exceed the
column limit:
;; check for lines that exceed some column limit
(setq-default
whitespace-line-column 100
whitespace-style '(face lines-tail))
(add-hook 'prog-mode-hook #'whitespace-mode)
If you would rather have Emacs highlight entire lines that exceed the column limit, then use the following instead (not in addition to):
;; check for lines that exceed some column limit
(setq-default
whitespace-line-column 100
whitespace-style '(face lines))
(add-hook 'prog-mode-hook #'whitespace-mode)
You can create the ~/.emacs
file if it does not
exist. If you have an ~/.emacs.el
or
~/.emacs.d/init.el
file, then you can place the lines
in that file instead of ~/.emacs
.
If, after adding the configuration lines above, you still have
trouble finding lines that exceed the column limit, then you can
ask Emacs to mark newlines with a $
by typing
M-x whitespace-newline-mode
then RET
(return).
Method height <= window height. You should limit the number of lines for a method so that the entire method can be seen on the screen at once. This includes the line(s) with the method's signature and opening curly brace, all lines in the body of the mthod (including blank lines), and the line with the method's ending curly brace. The method height does not include a method's Javadoc comment, however, it does include any comments contained within the body of the method.
Of all the style guidelines, this is the probably the most subjective and hardest to grade because everyone might have a different window size due to different terminal emulator and physical screen size configurations. Therefore, graders will be checking for compliance with the spirit of this guideline, which is: methods that are too big and/or repetitive should be refactored to include proper looping constructs and/or broken up into smaller methods to improve readability.
If you use Emacs, you can add the following lines to your
~/.emacs
file to enable line numbers:
;; add line numbers
(global-linum-mode 1)
;; display line numbers and column numbers
(setq line-number-mode t)
(setq column-number-mode t)
;; make sure the line numbers don't touch the text
(setq linum-format "%d ")
You can create the ~/.emacs
file if it does not
exist. If you have an ~/.emacs.el
or
~/.emacs.d/init.el
file, then you can place the lines
in that file instead of ~/.emacs
.
Javadoc Documentation (25 points): All methods and classes needs to be fully documented using Javadoc comments and appropriate Jaadoc tags. Each comment should provide a description of the method's functionality in the first sentence of the comment. This sentence needs to be a grammatically correct English sentence with proper punctuation. Further description can be provided in subsequent sentence.
Even if documentation is inherited from an interface, you must
explicitly include a Javadoc comment with either a new description
(if that makes sense) or make proper use of the
{@inheritDoc}
tag.
It should be noted that we do expect you to provide a Javadoc comment for each class in addition to a comment for each method within a class. The Javadoc comment for a class is placed directly above the class declaration as seen in the examples provided in the link referenced earlier.
In-line Documentation (25 points): Code blocks should be adequately documented using in-line comments. This is especially necessary when a block of code is not immediately understood by a reader (e.g., yourself or the grader).
Absolute Requirements
An absolute requirement is similar to a non-functional requirement, except that violating it will result in an immediate zero for the assignment. In many cases, a violation will prevent the graders from evaluating your functional requirements. No attempts will be made to modify your submission to evaluate other requirements.
Project Directory Structure: The location of
the default package for the source code should be a direct
subdirectory of cs1302-listadt
called
src
. When the project is compiled, the -d
option should be used with javac
to make the default
package for compiled code a direct subdirectory of
cs1302-listadt
called bin
.
If you follow this structure, then you would type the following
to compile your code, assuming you are in the top-level project
directory cs1302-listadt
:
$ javac -cp listadt.jar -d bin src/cs1302/list/ArrayStringList.java
$ javac -cp listadt.jar -d bin src/cs1302/list/LinkedStringList.java
Remember, when you compile .java
files
individually, there might be dependencies between the files. In
such cases, the order in which you compile the code matters. Also,
if more than one default package is needed (e.g.,
listadt.jar
and some other directory like
bin
), then a colon :
can be used to
separate each path in a list of multiple paths supplied to
-cp
. For an example, see "Setting the Classpath" in
the package tutorial.
Development Environment: This project must be implemented in Java 8, and it must compile and run correctly on Nike using the specific version of Java 8 that is setup according to the instructions provided by your instructor. For Spring 2019, these instructions were posted on Piazza @29.
If you decide to introduce additional .java
files
into your project, then they are expected to fulfill all
non-functional and absolute requirements, even if the main parts of
the project do not use them. You may assume graders will compile
your source code in an order that satisfies compilation
dependencies. You should remove any .java
files that
you do not need before submission.
cs1302.list.ArrayStringList
Storage
Requirement: You must use a basic Java array for this
class's storage. The initial size of the array does not have to be
the same size as the initial size of the list. Whenever the size of
the list is about to exceed the size of its array, the list should
dynamically allocate a new array of a larger size and copy the
contents over--please consider writing and documenting a private
support method to do this. If you use Java's
java.util.ArrayList
class or something similar, then
that will result in an immediate violation of this non-functional
requirement, regardless of any use of a regular array elsewhere in
the class. This requirement also prohibits any use of third-party
implementations of list or list-like interfaces.
cs1302.list.LinkedStringList
Storage
Requirement: You must use a sequence of
cs1302.listadt.StringList.Node
objects for this
class's storage. Unlike the array-based implementation in
ArrayStringList
, this type of storage is not limited
to the number of elements that can fit into an array (because there
is not an array). Instead, it's limited only by the available
memory for the Java program using the LinkedStringList
object. You may find sections 13.1 and 13.2 of the LDC textbook
useful reference material for this class. If you use Java's
java.util.LinkedList
class or something similar, then
that will result in an immediate violation of this non-functional
requirement, regardless of any use of any Node
objects
elsewhere in the class. This requirement also prohibits any use of
third-party implementations of list or list-like interfaces.
No Static Variables: Use of static variables is not allowed for this assignment. However, static constants are permitted.
Grading
This project will be graded using unit tests, none of which will be made available before the project deadline. You can test your implementations yourself via interface polymorphism.
ArrayStringList.java:
package cs1302.list;
import cs1302.listadt.StringList;
import java.lang.*;
/** Represents an {@code ArrayStringList} object that uses an
array to store strings. */
public class ArrayStringList implements StringList {
private String[] list; //list stored as an array
/** Creates an {@code ArrayStringList} object and initializes
list to be an array of size 0 */
public ArrayStringList() {
list = new String[0];
} //ArrayStringList
/**
* Creates an {@code ArrayStringList} object and copies all strings
from a specified list.
* @param other the list whose strings are to be copied
*/
public ArrayStringList(StringList other) {
list = new String[other.size()];
for(int i = 0; i < other.size(); i++) {
list[i] = other.get(i);
}
} //ArrayStringList
/**
* Inserts the specified string at the specified position in this
list.
* @param index index at which the specified string is to be
inserted
* @param s string to be inserted
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >} size())
*/
public boolean add(int index, String s) {
boolean add = false;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException("Index is out of range");
} else {
String[] list1 = new String[size() + 1];
int i = 0;
for(int n = 0; n < index; n++) {
list1[n] = list[n];
i++;
}
list1[i] = s;
for(int n = index + 1; n < list1.length; n++) {
list1[n] = list[n - 1];
}
list = list1;
add = true;
}
return add;
} //add
/**
* Inserts the strings contained in the specified list at the
specified position in this list,
* in the order in which they appear in the specified list.
* @param index index at which the specified string is to be
inserted
* @param sl string to be inserted
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified list is null
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >} size())
*/
public boolean add(int index, StringList sl) {
boolean add = false;
if (sl == null) {
throw new NullPointerException("StringList is null");
} else if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException("Index is out of range");
} else {
String[] list1 = new String[size() + sl.size()];
int i = 0;
for(int n = 0; n < index; n++) {
list1[n] = list[n];
i++;
}
for(int n = 0; n < sl.size(); n++) {
list1[i] = sl.get(n);
i++;
}
for(int n = index; n < size(); n++) {
list1[i] = list[n];
i++;
}
list = list1;
add = true;
}
return add;
} //add
/**
* Appends the specified string to the end of this list.
* @param s string to be appended
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean add(String s) {
boolean add = false;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
String[] list1 = new String[size() + 1];
for(int i = 0; i < size(); i++) {
list1[i] = list[i];
}
list1[list1.length - 1] = s;
list = list1;
add = true;
}
return add;
} //add
/**
* Appends the strings contained in the specified list to the end of
this list, in the order
* in which they appear in the specified list.
* @param sl list whose strings are to be appended
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified list is null
*/
public boolean add(StringList sl) {
boolean add = false;
if (sl == null) {
throw new NullPointerException("StringList is null");
} else {
String[] list1 = new String[this.size() + sl.size()];
int i = 0;
for(int n = 0; n < size(); n++) {
list1[n] = list[n];
i++;
}
for (int n = 0; n < sl.size(); n++) {
list1[i] = sl.get(n);
i++;
}
list = list1;
add = true;
}
return add;
} //add
/**
* Removes all of the stringns from this list.
* The list will be empty after this call returns.
*/
public void clear() {
String[] newList = new String[0];
list = newList;
} //clear
/**
* Returns true if this list contains the specified string.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that o.equals(s).
* @param o string whose presence in this list is to be tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean contains(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for(String s : list) {
if (o.equals(s)) {
contains = true;
}
}
}
return contains;
} //contains
/**
* Returns true if this list contains the specified string, ignoring
case.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that o.equalsIgnoreCase(s).
* @param o string whose presence in this list is to be tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean containsIgnoreCase(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for(String s : list) {
if (o.equalsIgnoreCase(s)) {
contains = true;
}
}
}
return contains;
} //containsIgnoreCase
/**
* Returns true if any string in this list contains the specified
substring.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that s.contains(o).
* @param o substring whose presence in this list is to be
tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified substring is
null
* @throws IllegalArgumentException if the specified substring is
empty
*/
public boolean containsSubstring(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for(String s : list) {
if (s.contains(o)) {
contains = true;
}
}
}
return contains;
} //containsSubstring
/**
* Returns an array containing all of the strings in this list in
proper
* sequence (from first to last element). The returned array will be
"safe"
* in that no references to it are maintained by this list.
* In other words, this method must allocate a new array even if
this list
* is backed by an array. The caller is thus free to modify the
returned array.
* @return an array containing all of the strings in this list in
proper sequence
*/
public String[] toArray() {
String[] array = new String[size()];
for(int i = 0; i < size(); i++) {
array[i] = list[i];
}
return array;
} //toArray
/**
* Returns the number of elements in this list. If this list
contains more than
* Integer.MAX_VALUE elements, then this method returns
Integer.MAX_VALUE.
* @return the number of elements in this list
*/
public int size() {
if(list.length > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
return list.length;
} //size
/**
* Returns true if this list contains no elements.
* @return true if this list contains no elements
*/
public boolean isEmpty() {
if(size() == 0) {
return true;
} else {
return false;
}
} //isEmpty
/**
* Returns the string at the specified position in this list.
* @param index index of the string to return
* @return the string at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String get(int index) {
String string = "";
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
string = list[index];
}
return string;
} //get
/**
* Replaces the string at the specified position in this list with
the specified element.
* @param index index at which the specified string is to be
inserted
* @param s string to be inserted
* @return the string previously at the specified position
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String set(int index, String s) {
String string = "";
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
string = list[index];
list[index] = s;
}
return string;
} //set
/**
* Removes the string at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from
their indices).
* Returns the string that was removed from the list.
* @param index index of the string to remove
* @return the string previously at the specified position in this
list
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String remove(int index) {
String string = "";
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
string = list[index];
String[] list1 = new String[size() - 1];
for(int i = 0; i < index; i++) {
list1[i] = list[i];
}
for (int i = index + 1; i < list.length; i++) {
list1[i-1] = list[i];
}
list = list1;
}
return string;
} //remove
/**
* Returns the index of the first occurrence of the specified string
in this list, or -1 if
* this list does not contain the string. More formally, returns the
lowest index i such that
* s.equals(get(i))), or -1 if there is no such index.
* @param s string to search for
* @return the index of the first occurrence of the specified string
in this list, or -1 if
* this list does not contain the string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public int indexOf(String s) {
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
int index = 0;
for (String string : list) {
if(s.equals(string)) {
return index;
}
index++;
}
}
return -1;
} //indexOf
/**
* Returns the index of the first occurrence of the specified
string, ignoring case, in this
* list, or -1 if this list does not contain the string. More
formally, returns the lowest
* index i such that s.equalsIgnoreCase(get(i))), or -1 if there is
no such index.
* @param s string to search for
* @return the index of the first occurrence of the specified
string, ignoring case, in this
* list, or -1 if this list does not contain the string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public int indexOfIgnoreCase(String s) {
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
int index = 0;
for (String string : list) {
if(s.equalsIgnoreCase(string)) {
return index;
}
index++;
}
}
return -1;
} //indexOfIgnoreCase
/**
* Builds and returns a new {@code StringList} from this list
without any duplicate strings.
* @return a new {@code StringList} which contains the first
occurance of every string in this
* list
*/
public StringList distinct() {
StringList list1 = new ArrayStringList();
for(String string : list) {
if(list1.indexOf(string) == -1) {
list1.add(string);
}
}
return list1;
} //distinct
/**
* Builds and returns a new {@code StringList} that contains the
strings from this list in
* reverse order.
* @return a new {@code StringList} with the strings from this list
in reverse order
*/
public StringList reverse() {
StringList list1 = new ArrayStringList();
for(int i = size() - 1; i >= 0; i--) {
list1.add(list[i]);
}
return list1;
} //reverse
/**
* Returns a string representation of this list with every string in
the sequence separated by
* the specified seprator string.
* @param sep the specified separator string
* @return string representation of this list with every string in
the sequence separated by sep
*/
public String makeString(String sep) {
String string = "";
if(size() != 0) {
for(int i = 0; i < size() - 1; i++) {
string = string + list[i] + sep;
}
string += list[list.length - 1];
}
return string;
} //makeString
/**
* Builds and returns a new {@code StringList} that contains the
strings from this list between
* the specified {@code fromIndex}, inclusive, and {@code toIndex},
exclusive. If
* {@code fromIndex} and {@code toIndex} are in bounds and equal,
then the returned list is
* empty.
* @param fromIndex low endpoint (inclusive) of the splice
* @param toIndex high endpoint (exclusive) of the splice
* @return a new {@code StringList} with the strings from this list
from the specified range
* @throws IndexOutOfBoundsException for an illegal endpoint index
value
* (fromIndex {@literal <} 0 || toIndex {@literal >} size ||
fromIndex {@literal >} toIndex)
*/
public StringList splice(int fromIndex, int toIndex) {
StringList list1 = new ArrayStringList();
if(fromIndex < 0 || toIndex > size() || fromIndex >
toIndex) {
throw new IndexOutOfBoundsException("Illegal endpoint index
value");
} else {
for(int i = fromIndex; i < toIndex; i++) {
list1.add(list[i]);
}
}
return list1;
} //splice
}
LinkedStringList.java:
package cs1302.list;
import cs1302.listadt.StringList;
import cs1302.listadt.StringList.Node;
/** Represents a {@code LinkedStringList} object that uses nodes
to store strings. */
public class LinkedStringList implements StringList {
StringList.Node list; //list stored as a linked list
/** Creates a LinkedStringList object with an empty node as its
first and only node. */
public LinkedStringList() {
list = new StringList.Node();
} //LinkedStringList
/**
* Creates a {@code LinkedStringList} object with an empty node as
its first node and then
* appends a copy of the specified list to the end.
* @param other the list whose strings are to be copied
*/
public LinkedStringList(StringList other) {
list = new StringList.Node();
StringList.Node current = list;
for(int i = 0; i < other.size(); i++) {
String s = other.get(i);
current.setNext(new StringList.Node(s, null));
current = current.getNext();
}
} //LinkedStringList
/**
* Returns the number of elements in this list. If this list
contains more than
* Integer.MAX_VALUE elements, then this method returns
Integer.MAX_VALUE.
* @return the number of elements in this list
*/
public int size() {
int size = 0;
StringList.Node current = list.getNext();
while (current != null) {
size++;
if(size > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
current = current.getNext();
}
return size;
} //size
/**
* {@inheritdoc}
* @return true if this list contains no elements
*/
public boolean isEmpty() {
if (size() == 0) {
return true;
} else {
return false;
}
} //isEmpty
/**
* Returns true if this list contains the specified string.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that o.equals(s).
* @param o string whose presence in this list is to be tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean contains(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for (int i = 0; i < size(); i++) {
if(o.equals(get(i))) {
contains = true;
}
}
}
return contains;
} //contains
/**
* Returns true if this list contains the specified string, ignoring
case.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that o.equalsIgnoreCase(s).
* @param o string whose presence in this list is to be tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean containsIgnoreCase(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for (int i = 0; i < size(); i++) {
if(o.equalsIgnoreCase(get(i))) {
contains = true;
}
}
}
return contains;
} //containsIgnoreCase
/**
* Returns true if any string in this list contains the specified
substring.
* More formally, returns true if, and only if, this list contains
at least
* one element s such that s.contains(o).
* @param o substring whose presence in this list is to be
tested
* @return true if this list contains the specified string
* @throws NullPointerException if the specified substring is
null
* @throws IllegalArgumentException if the specified substring is
empty
*/
public boolean containsSubstring(String o) {
boolean contains = false;
if (o == null) {
throw new NullPointerException("String is null");
} else if (o.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for (int i = 0; i < size(); i++) {
if(o.contains(get(i))) {
contains = true;
}
}
}
return contains;
} //containsSubstring
/**
* Returns an array containing all of the strings in this list in
proper
* sequence (from first to last element). The returned array will be
"safe"
* in that no references to it are maintained by this list.
* In other words, this method must allocate a new array even if
this list
* is backed by an array. The caller is thus free to modify the
returned array.
* @return an array containing all of the strings in this list in
proper sequence
*/
public String[] toArray() {
String[] array = new String[size()];
for(int i = 0; i < size(); i++) {
array[i] = get(i);
}
return array;
} //toArray
/**
* Appends the specified string to the end of this list.
* @param s string to be appended
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public boolean add(String s) {
boolean add = false;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
StringList.Node current = list;
while(current.getNext() != null) {
current = current.getNext();
}
current.setNext(new StringList.Node(s, null));
add = true;
}
return add;
} //add
/**
* Appends the strings contained in the specified list to the end of
this list, in the order
* in which they appear in the specified list.
* @param sl list whose strings are to be appended
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified list is null
*/
public boolean add(StringList sl) {
boolean add = false;
if (sl == null) {
throw new NullPointerException("StringList is null");
} else {
StringList.Node current = getNode(size());
for(int i = 0; i < sl.size(); i++) {
current.setNext(new StringList.Node(sl.get(i), null));
current = current.getNext();
}
add = true;
}
return add;
} //add
/**
* Inserts the specified string at the specified position in this
list.
* @param index index at which the specified string is to be
inserted
* @param s string to be inserted
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >} size())
*/
public boolean add(int index, String s) {
boolean add = false;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
if (index == 0) {
StringList.Node front = new StringList.Node();
StringList.Node temp = new StringList.Node(s,
list.getNext());
front.setNext(temp);
list = front;
} else if (index == size()) {
add(s);
} else {
StringList.Node front = list.getNext();
for (int i = 0; i < index - 1; i++) { //sets front to the node
before the index node
front = front.getNext();
}
StringList.Node back = new StringList.Node(s,
front.getNext());
front.setNext(back); //merges the 2 nodes with the added string in
between
}
add = true;
}
return add;
} //add
/**
* Inserts the strings contained in the specified list at the
specified position in this list,
* in the order in which they appear in the specified list.
* @param index index at which the specified string is to be
inserted
* @param sl list to be inserted
* @return true if this list changed as a result of the call; false
otherwise
* @throws NullPointerException if the specified list is null
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >} size())
*/
public boolean add(int index, StringList sl) {
boolean add = false;
if (sl == null) {
throw new NullPointerException("StringList is null");
} else if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
if (index == size()) {
add(sl);
} else {
StringList.Node front = list.getNext();
for (int i = 0; i < index - 1; i++) { //sets front to the node
before the index node
front = front.getNext();
}
StringList.Node back = front.getNext(); //sets back to the node
currently at index
for (int i = 0; i < sl.size(); i++) { //adds sl to front
front.setNext(new StringList.Node(sl.get(i)));
front = front.getNext();
}
front.setNext(back); //merges the 2 lists together
add = true;
}
}
return add;
} //add
/**
* Returns a reference to the index-th node in a linked list
* @param index the index of the node
* @return a reference to the index-th node
*/
private StringList.Node getNode(int index) {
StringList.Node current;
if (size() == 0) {
current = list;
} else {
current = list.getNext();
for (int i = 0; i < index - 1; i++) {
current = current.getNext();
}
}
return current;
} //getNode
/**
* Returns the string at the specified position in this list.
* @param index index of the string to return
* @return the string at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String get(int index) {
String string = "";
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
StringList.Node current = list.getNext(); //Skips the first node
that is always empty
for (int i = 0; i < index; i++) {
current = current.getNext();
}
string = current.getStr();
}
return string;
} //get
/**
* Replaces the string at the specified position in this list with
the specified element.
* @param index index at which the specified string is to be
inserted
* @param s string to be inserted
* @return the string previously at the specified position
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String set(int index, String s) {
String string = "";
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
StringList.Node current = getNode(index + 1);
string = current.getStr();
current.setStr(s);
}
return string;
} //set
/**
* Removes the string at the specified position in this list.
* Shifts any subsequent elements to the left (subtracts one from
their indices).
* Returns the string that was removed from the list.
* @param index index of the string to remove
* @return the string previously at the specified position in this
list
* @throws IndexOutOfBoundsException if the index is out of
range
* (index {@literal <} 0 || index {@literal >}= size())
*/
public String remove(int index) {
String string = "";
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
StringList.Node front = list.getNext();
if(index == 0) { //if you want to remove the first element in the
list
string = front.getStr();
list = front;
} else {
for (int i = 0; i < index - 1; i++) { //sets front to the node
before the index node
front = front.getNext();
}
string = front.getNext().getStr();
//back equals the node after the index node
StringList.Node back = front.getNext().getNext();
front.setNext(back); //merges front and back, omitting the index
node
}
}
return string;
} //remove
/**
* Returns the index of the first occurrence of the specified string
in this list, or -1 if
* this list does not contain the string. More formally, returns the
lowest index i such that
* s.equals(get(i))), or -1 if there is no such index.
* @param s string to search for
* @return the index of the first occurrence of the specified string
in this list, or -1 if
* this list does not contain the string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public int indexOf(String s) {
int index = -1;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for(int i = 0; i < size(); i++) {
if(s.equals(get(i))) {
index = i;
}
}
}
return index;
} //indexOf
/**
* Returns the index of the first occurrence of the specified
string, ignoring case, in this
* list, or -1 if this list does not contain the string. More
formally, returns the lowest
* index i such that s.equalsIgnoreCase(get(i))), or -1 if there is
no such index.
* @param s string to search for
* @return the index of the first occurrence of the specified
string, ignoring case, in this
* list, or -1 if this list does not contain the string
* @throws NullPointerException if the specified string is
null
* @throws IllegalArgumentException if the specified string is
empty
*/
public int indexOfIgnoreCase(String s) {
int index = -1;
if (s == null) {
throw new NullPointerException("String is null");
} else if (s.equals("")) {
throw new IllegalArgumentException("String is empty");
} else {
for(int i = 0; i < size(); i++) {
if(s.equalsIgnoreCase(get(i))) {
index = i;
}
}
}
return index;
} //indexOfIgnoreCase
/**
* Removes all of the stringns from this list.
* The list will be empty after this call returns.
*/
public void clear() {
StringList.Node list1 = new StringList.Node();
list = list1;
} //clear
/**
* Builds and returns a new {@code StringList} from this list
without any duplicate strings.
* @return a new {@code StringList} which contains the first
occurance of every string in this
* list
*/
public StringList distinct() {
StringList list1 = new LinkedStringList();
StringList.Node current = list.getNext();
for(int i = 0; i < size(); i++) {
if(list1.indexOf(current.getStr()) == -1) {
list1.add(current.getStr());
}
current = current.getNext();
}
return list1;
} //distinct
/**
* Builds and returns a new {@code StringList} that contains the
strings from this list in
* reverse order.
* @return a new {@code StringList} with the strings from this list
in reverse order
*/
public StringList reverse() {
StringList list1 = new LinkedStringList();
for(int i = size() - 1; i >= 0; i--) {
list1.add(get(i));
}
return list1;
} //reverse
/**
* Returns a string representation of this list with every string in
the sequence separated by
* the specified seprator string.
* @param sep the specified separator string
* @return string representation of this list with every string in
the sequence separated by sep
*/
public String makeString(String sep) {
String string = "";
if(size() != 0) {
for(int i = 0; i < size() - 1; i++) {
string = string + get(i) + sep;
}
string = string + get(size() - 1);
}
return string;
} //makeString
/**
* Builds and returns a new {@code StringList} that contains the
strings from this list between
* the specified {@code fromIndex}, inclusive, and {@code toIndex},
exclusive. If
* {@code fromIndex} and {@code toIndex} are in bounds and equal,
then the returned list is
* empty.
* @param fromIndex low endpoint (inclusive) of the splice
* @param toIndex high endpoint (exclusive) of the splice
* @return a new {@code StringList} with the strings from this list
from the specified range
* @throws IndexOutOfBoundsException for an illegal endpoint index
value
* (fromIndex {@literal <} 0 || toIndex {@literal >} size() ||
fromIndex {@literal >} toIndex)
*/
public StringList splice(int fromIndex, int toIndex) {
StringList list1 = new LinkedStringList();
if (fromIndex < 0 || toIndex > size() || fromIndex >
toIndex) {
throw new IndexOutOfBoundsException("Index out of bounds");
} else {
for(int i = fromIndex; i < toIndex; i++) {
list1.add(get(i));
}
}
return list1;
} //splice
}
_______________________________________________________________
Please upvote so that I could answer more such questions for you :)