Using generics and trying to get rid of the unsafe operations warning - java

Here is my code, but I keep getting the "Note: LinkedListAdd.java uses unchecked or unsafe operations." I'm trying to do what I can to get rid of it, but nothing seems to be working. The base class compiles fine and has no warning, and the check seems to be coming from the add all method. Any ideas?
public class LinkedListAdd<E extends Comparable <E> > extends LinkedList<E>
{
public LinkedListAdd()
{
super();
}
public <E extends Comparable<E> > boolean addAll(final int index, final E[] array)
{
if(index < 0 || index > this.size())
throw new IndexOutOfBoundsException("Index out of bounds");
if(array == null)
throw new NullPointerException("Null array");
Node nn = null;
for(int y = array.length - 1; y >= 0; y--)
{
nn = new Node(array[y], null);
if(this.size() == 0)
{
this.head.next = nn;
this.size += 1;
}
else
{
Node cur = this.head.next, prev = null;
for(int x = 0; x < index; x++)
{
prev = cur;
cur = cur.next;
}
if(prev == null)
{
nn.next = cur;
this.head.next = nn;
this.size += 1;
}
else
{
prev.next = nn;
nn.next = cur;
this.size += 1;
}
}
}
if(nn == null)
return false;
return true;
}
}//end class LinkedListSort
Here is the base class
public class LinkedList<E extends Comparable <E> >
{
protected static class Node<E extends Comparable <E> >
{
public E data;
public Node<E> next;
public Node()
{
this.next = null;
this.data = null;
}// end DVC
public Node(final E data, final Node<E> next)
{
this.next = next;
this.data = data;
}// end EVC
}// end class Node
protected Node <E> head;
protected int size;
public LinkedList()
{
this.head = new Node<>();
this.size = 0;
}
public void clear()
{
this.head = null;
this.size = 0;
}// end clear
public int size(){return this.size;}
public void addFirst(final E data)
{
this.head.next = new Node<>(data, this.head.next);
size ++;
}// end
public String toString()
{
String temp = "List size: " + this.size;
if(this.head.next == null)
return temp += "\nEmpty List";
else
{
temp += "\n";
Node<E> cur = head.next;
while(cur != null)
{
temp += cur.data + " ";
cur = cur.next;
}
return temp;
}// end else
}// end toString
}// end class

There's a couple of things I'd recommend doing; firstly I'd add methods for get/set on your head/next/size/data and make those fields private
With regards to your generics;
the method signature should be
public boolean addAll(final int index, final E[] array)
and your declarations for nodes in that method need to be
Node<E> node

Related

Add(index, element) method

I am implementing a method add(int index, E element) that is supposed to insert the specified element at the specified index in a list and shift the element currently at that position and any subsequent elements to the right. Does anyone know why my method does not work when my code is:
newNode.setNext(temp.getNext());
newNode.setPrev(temp);
newNode.getNext().setPrev(newNode);
temp.setNext(newNode);
at the end of the method but works when I have only
newNode.setNext(temp.getNext());
temp.setNext(newNode);
My code:
public class DoubleLinkedList<E> implements IDoubleLinkedList<E> {
DLLNode head;
DLLNode tail;
int size = 0;
#Override
public void add(int index, E element) throws IndexOutOfBoundsException {
if (index > size) {
throw new IndexOutOfBoundsException();
}
if (index < 0) {
throw new IndexOutOfBoundsException();
}
if (head == null) {
head = new DLLNode(element);
tail = head;
}
else if (index == 0) {
DLLNode temp = new DLLNode(element);
temp.setNext(head);
head = temp;
} else {
DLLNode temp = head;
for (int i = 1; i < index; i++) {
temp = temp.getNext();
}
DLLNode newNode = new DLLNode(element);
newNode.setNext(temp.getNext());
newNode.setPrev(temp);
newNode.getNext().setPrev(newNode);
temp.setNext(newNode);
}
size ++;
}
Node class for my DoublyLinkedlist:
public class DLLNode<E> {
private DLLNode<E> next;
private DLLNode<E> prev;
private E element;
public DLLNode(E element){
this.element=element;
prev=null;
next=null;
}
public DLLNode(E element, DLLNode prev, DLLNode next) {
this.element=element;
this.prev=prev;
this.next=next;
}
public E getData(){
return element;
}
public void setData(E element){
this.element=element;
}
public DLLNode getPrev(){
return prev;
}
public DLLNode getNext(){
return next;
}
public void setPrev(DLLNode where){
prev=where;
}
public void setNext(DLLNode where){
next=where;
}}
It doesn't work for three reasons that I can see:
In the if (index == 0) block, you never set the prev value of the head node.
In the else block, you never check if you're at the end of the list, so you'll get a NullPointerException if you are.
In both if (index == 0) block and else block, you don't set tail if the new node is the last node.
On a side note: You're using raw generics all over. Never use DLLNode without a < immediately after it. Basically, change all DLLNode to DLLNode<E>.
Here's how you test your own code.
Add this method to DLLNode:
void verifyIntegrity() {
if (this.prev != null && this.prev.next != this)
throw new AssertionError("prev.next is corrupt");
if (this.next != null && this.next.prev != this)
throw new AssertionError("next.prev is corrupt");
}
Add this method to DoubleLinkedList:
void verifyIntegrity() {
int count = 0;
DLLNode<E> last = this.head;
for (DLLNode<E> node = this.head; node != null; count++, last = node, node = node.getNext())
node.verifyIntegrity();
if (this.tail != last)
throw new AssertionError("tail is corrupt");
if (this.size != count)
throw new AssertionError("size is corrupt");
}
Now test you code like this:
DoubleLinkedList<Integer> listHead = new DoubleLinkedList<>();
DoubleLinkedList<Integer> listTail = new DoubleLinkedList<>();
DoubleLinkedList<Integer> listMid = new DoubleLinkedList<>();
listHead.verifyIntegrity();
listTail.verifyIntegrity();
listMid.verifyIntegrity();
for (int i = 0; i < 10; i++) {
listHead.add(0, i);
listTail.add(i, i);
listMid.add(i / 2, i);
listHead.verifyIntegrity();
listTail.verifyIntegrity();
listMid.verifyIntegrity();
}

Reverse generic LinkedList by using swap method

public class SimpleLinkedList<E> {
public Node<E> head;
public int size;
public void add(E e) {
++this.size;
if (null == head) {
this.head = new Node();
head.val = e;
} else {
Node<E> newNode = new Node();
newNode.val = e;
newNode.next = head;
this.head = newNode;
}
}
public void swap(E val1, E val2) {
if (val1.equals(val2)) {
return;
}
Node prevX = null, curr1 = head;
while (curr1 != null && !curr1.val.equals(val1)) {
prevX = curr1;
curr1 = curr1.next;
}
Node prevY = null, curr2 = head;
while (curr2 != null && !curr2.val.equals(val2)) {
prevY = curr2;
curr2 = curr2.next;
}
if (curr1 == null || curr2 == null) {
return;
}
if (prevX == null) {
head = curr2;
} else {
prevX.next = curr2;
}
if (prevY == null) {
head = curr1;
} else {
prevY.next = curr1;
}
Node temp = curr1.next;
curr1.next = curr2.next;
curr2.next = temp;
}
public void reverse() {
Node<E> prev = null;
Node<E> current = head;
Node<E> next = null;
while (current != null) {
next = current.next;
current.next = prev;
prev = current;
current = next;
}
head = prev;
}
public static class Node<E> {
public Node<E> next;
public E val;
}
}
public class SimpleLinkedListTest {
#Test
public void testReverseMethod() {
SimpleLinkedList<Integer> myList = new SimpleLinkedList<>();
for (int i = 0; i < 10; i++) {
myList.add(i);
}
SimpleLinkedList<Integer> expectedList = new SimpleLinkedList<>();
for (int i = 9; i > -1; i--) {
expectedList.add(i);
}
myList.reverse();
assertTrue(AssertCustom.assertSLLEquals(expectedList, myList));
}
}
What would be the most optimal way to reverse generic LinkedList by using the swap method?
before reverse method :
(head=[9])->[8]->[7]->[6]->[5]->[4]->[3]->[2]->[1]->[0]-> null
after reverse() method :
(head=[0])->[1]->[2]->[3]->[4]->[5]->[6]->[7]->[8]->[9]-> null
What you need to do is divide the list in half. If the list size is odd the one in the middle will remain in place. Then swap elements on either side in a mirror like fashion. This should be more efficient than O(n^2)
reverse(){
Node current = this.head;
int half = this.size/2;
int midElement = this.size % 2 == 0 ? 0: half + 1;
Stack<Node<E>> stack = new Stack<Node<E>>();
for(int i = 0; i < this.size; i++){
if (i < = half)
stack.push(current);
else{
if (i == midElement)
continue;
else
swap(stack.pop(), current);
current = current.next;
}
}
swap(Node<E> v, Node<E> v1){
E tmp = v.value;
v.value = v1.value;
v1.value = tmp;
}
This is a little bit of pseudo java. It is missing still the checks for size = 0 or size = 1 when it should return immediately. One for loop. Time Complexity O(n). There is also the need to check when size = 2, swap(...) is to be invoked directly.
Based on the #efekctive 's idea, there a solution. The complexity is a little bit worse than O^2 but no need changes in the swap method, no need in usage of another collection. The code below passes the unit test, however, be careful to use it there could be a bug related to size/2 operation. Hope this help.
public void reverse() {
Node<E> current = head;
SimpleLinkedList<E> firstHalf = new SimpleLinkedList<>();
SimpleLinkedList<E> secondHalf = new SimpleLinkedList<>();
for (int i = 0; i < size; i++) {
if (i >= size / 2) {
firstHalf.add(current.val);
} else {
secondHalf.add(current.val);
}
current = current.next;
}
SimpleLinkedList<E> secondHalfReverse = new SimpleLinkedList<>();
for (int i = 0; i < secondHalf.size(); i++) {
secondHalfReverse.add(secondHalf.get(i));
}
for (int i = 0; i < size / 2; i++) {
if (secondHalfReverse.get(i) == firstHalf.get(i)) {
break;
}
swap(secondHalfReverse.get(i), firstHalf.get(i));
}
}

Issues with Objects in a linkedlist

On my count method, i am trying to compare the object being sent with the object calling it, and I have no idea why i can not cal o.get(i) to get the value for Object o being passed. It tells me the method cannot be found even though i can call get(i) normally. Any ideas how i can get the value for the object getting passed so i can compare them?
public class GenericLinkedList<E> implements List<E> {
private class Node<E>{
private E data;
private Node<E> next;
}
private E data;
private Node<E> head = null;
private int size = 0;
private Node<E> nodeAt(int index){
Node<E> curNode = head;
int curIndex = 0;
while(curIndex < index){
curNode = curNode.next;
curIndex++;
}
return curNode;
}
#Override
public E get(int index) {
return nodeAt(index).data;
}
#Override
public void add(E value) {
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else{
Node<E> curNode = nodeAt(size - 1);
curNode.next = node;
}
size++;
}
public void add(int index, E value){
Node<E> node = new Node<E>();
node.data = value;
if(size == 0){
head = node;
}else if(index == 0){
node.next = head;
head = node;
}else{
Node<E> curNode = nodeAt(index - 1);
node.next = curNode.next;
curNode.next = node;
}
size++;
}
#Override
public void remove(int index) {
if(index == 0){
head = head.next;
}else{
Node<E> curNode = nodeAt(index - 1);
curNode.next = curNode.next.next;
}
size--;
}
#Override
public void set(int index, E value) {
nodeAt(index).data = value;
}
public String toString(){
String s = "";
Node<E> curNode = head;
s += curNode.data +" -> ";
while(curNode.next != null){
curNode = curNode.next;
s += curNode.data +" -> ";
}
s += "null";
return s;
}
public void clear() {
for (int i = 0; i < size; i++)
set(i, null);
size = 0;
}
#Override
public void removeAll(E o)//Clears out the array object by setting everything to null
{
for(int i = 0; i < this.size; i++)
{
}
}
#Override
public int count(Object o)
{
System.out.println(o);
int count = 0;
for(int i = 0; i< size;i++)
{
if(get(i) == o.get(i))
{
count++;
}
}
return count;
/*int count = 0;
for(int i = 0;i<this.size;i++)
{
for(int j = 0;i<size;j++)
{
}
}
return count;*/
}
public void reverse()
{
int x = size;
for(int i = 0; i < this.size; i++)
{
E temp = this.get(x);
this.set(x, get(i));
this.set(i, temp);
x++;
}
}
public Object subList(int beginIndex, int endIndex)
{
int j = 0;
GenericLinkedList<E> LinkedList = new GenericLinkedList<E>();
if(beginIndex == endIndex)
return LinkedList;
else if(beginIndex > endIndex||endIndex>size||beginIndex<0)
{
return null;
}
else
{
for(int i = beginIndex; i <= endIndex;i++)
{
LinkedList.add(get(i));
j++;
}
}
return LinkedList;
}
public static void main(String[] args) {
GenericLinkedList<Integer> myList = new GenericLinkedList<Integer>();
myList.add(4);
myList.add(7);
myList.add(123123);
System.out.println(myList.get(2));
GenericLinkedList<Integer> myList2 = new GenericLinkedList<Integer>();
myList2.add(4);
myList2.add(7);
myList2.add(8);
myList2.add(3,999);
System.out.println(myList2);
System.out.println(myList.count(myList2));
//System.out.println(myList2);
// myList2.clear();//Testing our clear class
// System.out.println(myList2);
//System.out.println(myList2.subList(1, 3));//Testing our clear class
// System.out.println(myList2);
}
}
You have a problem when trying to call o.get() because it is an object of the base type Object which has no method get defined. To get the proper result you have two possible solutions....
The short solution is to type cast.
((GenericLinkedList<Object>)o).get(i)
Or a more easily readable solution is to change the signature of your count method:
public int count(GenericLinkList<E> list) {
...
}
Change your count method to public int GenericLinkedList(Object o)
If you use Object as the type of the parameter, you can only call the methods which are available on Object.

Linked List class to build strings, trouble with constructor, java

I'm struggling to construct a Linked List object for building strings. My class LString is meant to mimic a String or StringBuilderobject. Instead of arrays, it uses a linked list to form strings. I'm unsure of how to form the constructor though.
Here is my code so far:
public class LString {
// 2. Fields
node front;
//node tail;
int size;
// 1. Node class
private class node {
char data;
node next;
//constructors
//1. default
public node (){
}
//2. data
public node (char newData){
this.data = newData;
}
//3. data + next
public node (char newData, node newNext){
this.data = newData;
this.next = newNext;
}
}
// 3. Constructors
public LString(){
this.size = 0;
this.front = null;
}
public LString(String original) {
}
// 4. Methods
public int length() {
return this.size;
}
public int compareTo(LString anotherLString) {
return 0;
}
public boolean equals(Object other) {
if (other == null || !(other instanceof LString)) {
return false;
}
else {
LString otherLString = (LString)other;
return true;
}
}
public char charAt(int index) {
return 'a';
}
public void setCharAt(int index, char ch) {
ch = 'a';
}
public LString substring(int start, int end) {
return null;
}
public LString replace(int start, int end, LString lStr) {
return null;
}
//append
public void append (char data){
this.size++;
if (front == null){
front = new node(data);
return;
}
node curr = front;
while (curr.next != null){
curr = curr.next;
}
curr.next = new node(data);
}
//prepend
public void prepend (char data){
/*node temp = new node(data);
temp.next = front;
front = temp;*/
front = new node(data, front);
size++;
}
//delete
public void delete(int index){
//assume that index is valid
if (index == 0){
front = front.next;
} else {
node curr = front;
for (int i = 0; i < index - 1; i++){
curr = curr.next;
}
curr.next = curr.next.next;
}
size--;
}
//toString
public String toString(){
StringBuilder result = new StringBuilder();
result.append('[');
node curr = front;
while (curr != null){
result.append(curr.data);
if (curr.next != null){
result.append(',');
}
curr = curr.next;
}
result.append(']');
return result.toString();
}
//add (at an index)
public void add(int index, char data){
if (index == 0){
front = new node(data, front);
} else {
node curr = front;
for (int i = 0; i < index - 1; i++){
curr = curr.next;
}
curr.next = new node(data, curr.next);
}
}
}
Many of the methods are stubs, so the class will compile with another test file. I don't think I need to include it to find the issue though.
Thanks for the help.
You can build your LString constructor in different ways. One way I can think of is to accepting char[] and store it in your internal LinkedList. You can take a look at String constructors in here to get more ideas.

Program won't compile completely without giving an error of parsing

I'm writing this code to implement a stack as a linked list but I keep getting an error when I compile this part of the code and can't figure out why
I definitely know that it shouldn't be giving me this error since there are enough brackets and none of them are out of place I hope
The Error:
C:\Users\Michelle\Desktop\ITB\Semester 5\Data Structures & Algorithms\Assignment\ListReference.java:108: error: reached end of file while parsing
}
^
1 error
My Code:
public class ListReference implements StackInterface {
private Node top;
//private Object item;
private int NumItems;
public ListReference() {
NumItems = 0;
top = new Node(null);
}
public boolean isEmpty() {
return NumItems == 0;
}
public int size() {
return NumItems;
}
/*public Node find(int index) {
Node curr = tail;
for(int skip = 1; skip < index; skip++) {
curr.getNext();
}
return curr;
}*/
public Object get(int index) {
if(index <= 0)
return null;
Node ListReference = top.getNext();
for(int i=1; i < index; i++) {
if (ListReference.getNext() == null)
return null;
ListReference = ListReference.getData();
}
}
public void add(int index, Object item) {
Node ListReferenceTemp = new Node(item);
Node ListRefCurr = top;
while(ListRefCurr.getNext() != null) {
ListRefCurr = ListRefCurr.getNext();
}
ListRefCurr.setNext(ListReferenceTemp);
NumItems++;
}
public void add(Object data) {
Node ListReferenceTemp = new Node(item);
Node ListRefernce = top;
for(int i=1; i < index && ListReference.getNext() != null; i++) {
ListReference = ListReference.getNext();
}
ListReferenceTemp.setNext(ListReference.getNext());
ListReference.setNext(ListReferenceTemp);
NumItems++;
}
// removes the element at the specified position in this list.
public boolean remove(int index) {
// if the index is out of range, exit
if (index < 1 || index > size())
return false;
Node ListRefCurr = top;
for (int i = 1; i < index; i++) {
if (ListRefCurr.getNext() == null) {
return false;
}
ListRefCurr = ListRefCurr.getNext();
}
ListRefCurr.setNext(ListRefCurr.getNext().getNext());
NumItems--; // decrement the number of elements variable
return true;
}
public String toString() {
Node ListReference = top.getNext();
String output = "";
while (ListREference != null) {
output += "[" + ListRefCurr.getData().toString() + "]";
ListRefCurr = ListRefCurr.getNext();
}
return output;
}

Categories

Resources