I am trying to add a linkedlist to another linkedlist using a method called addList in the MyLinkedList class. What I'm stuck on is how to implement the method so that I can add a linkedlist to another linkedlist of index location of my choosing.
Here's what I have in MyLinkedList:
public void addList(int index, E e){
if(index == 0){
addFirst(e);
} else if (index >= size){
addLast(e);
}
else{
Node<E> current = head;
for(int i = 1; i < index; i++){
current = current.next;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).next = temp;
size++;
}
}
I know this method won't work, I've tried it.
In my program itself, I have these:
public class linkedlistwork {
public static void main(String[] args) {
MyLinkedList<String> alpha = new MyLinkedList<String>();
alpha.add("hello");
alpha.add("world");
alpha.add("this");
System.out.println(alpha);
MyLinkedList<String> beta = new MyLinkedList<String>();
beta.add("is");
beta.add("java");
beta.add("rocks");
System.out.println(beta);
alpha.addList(1, beta);
System.out.println(alpha);
}
}
The correct output would be something like:
OUTPUT:
[hello, is, java, rocks, world, this]
My program would not run, an error occurred in this line
alpha.addList(1, beta);
on the "beta" part, it says:
method addList in class MyLinkedList cannot be applied to given types;
required: int,String
found: int,MyLinkedList
reason: actual argument MyLinkedList cannot be converted to String by method invocation conversion
where E is a type-variable:
E extends Object declared in class MyLinkedList
How would I fix my method so that I can use it correctly?
Thanks in advance!!
It appears to me that your addList method signature is the problem.
It should look like:
public void addList(int index, List<E> list)
You need to have a method for adding MyLinkedList<String>. Something like this would do
public void addList(int index, MyLinkedList<E> beta){
//Somehow loop through the MyLinkedList, and do this.
add(index+i,beta(i));
}
Related
What I am trying to do is to traverse through the LinkedList and then print out. I tried Googling what might be wrong but no luck till now. I already apologize if this is stupid question.
import java.util.LinkedList;
public class Main {
Node head;
static class Node{
int data;
Node next;
Node( int d ) {
this.data = d;
next = null;
}
}
public void printList(){
Node n = head;
while(n != null) {
System.out.print(n.data + " ");
n = n.next;
}
}
public static void main(String[] args) {
LinkedList llist = new LinkedList();
llist.head = new Node(1);
Node second = new Node(2);
Node third = new Node(3);
llist.head.next = second;
second.next = third;
llist.printList();
}
}
Error upon compiling
Current file warnings and errors
You weren't really clear about what you were trying to do here. Are you trying to create an own implementation of a linked list? Or are you simply trying to play around with java.util.LinkedList?
With the information gathered from your comments, we can tell that you are in fact trying to create your own implementation of a linked list.
So there are a few steps to take to fix your code. Firstly, remove the import java.util.LinkedList, as you apparently don't actually want to use that.
Then rename your outer class (which is currently Main) to something that makes sense, i.e. MyLinkedList. (Also don't forget to also rename the .java file)
public class MyLinkedList {
Node head;
...
Then in your main method, you need to actually use your implementation:
public static void main(String[] args) {
MyLinkedList llist = new MyLinkedList();
...
}
Then, you should be able to work forward from here.
In my opinion the error start as from the line
llist.head = new Node (1);
Because head is not defined inLinkedList.
You must review the documentation of LinkedList and the existing methods
What is the code that goes into: void changeElem(String oldStr, String newStr)?
I have a driver's class with:
public static void main(String[] args) {
// create empty list
SimpleLinkedList list = new SimpleLinkedList(null);
// add some elements in the list in
// reverse order so that list is sorted
list.addElement("W");
list.addElement("T");
list.addElement("P");
list.addElement("L");
list.addElement("K");
list.addElement("B");
list.printList();
System.out.println("change W to X");
list.changeElem("W", "X");
}
I am supposed to make a new method called “changeElem” in another class where
void changeElem(String oldStr, String newStr) but I am not sure how.
The answer by manikanta is right; however, changeElement(List list, String string, String replacement) requires you to pass the List as a parameter, which means you can't use it in the context list.changeElement("W", "X").
I'm assuming SimpleLinkedList is a Java class that you have implemented.
To use the method as list.changeElement("W", "X") instead of changeElement(list, "W", "X"), you need to add the method changeElement to the SimpleLinkedList class (which I think is actually your question).
Since actual implementation of the class isn't known, something like this:
public class SimpleLinkedList {
public void add(String str) {
//This should be an existing method, for example
}
//Assuming this is the implementation
private class Node {
String data;
Node nextNode;
}
private Node firstNode; //Should be set/unset in your add/remove method
//New method. To keep the order of your list, iterate and replace individually
public void changeElement(String str, String replacement) {
for (Node n = firstNode; n != null; n = n.nextNode) {
if (str.equals(n.data)) {
n.data = replacement;
break; //If you want to replace only one instance
}
}
}
}
Also, when in doubt: Look at Java's source code. What you basically want to do is find the place where str is and then replace it.
That's almost the Java LinkedList#indexOf method, except instead of returning index when you find str, you're replacing it. Java's LinkedList#indexOf() implementation.
We just have to add the replacement string at your intended location and then we should remove the unwanted string.
public static void main(String[] args) {
/* // create empty list
* LinkedList list = new LinkedList(null);
*/
LinkedList listLinked = new LinkedList<String>();
// add some elements in the list in
// reverse order so that list is sorted
listLinked.add("W");
listLinked.add("T");
listLinked.add("P");
listLinked.add("L");
listLinked.add("K");
listLinked.add("B");
changeElement(listLinked, "W", "X");
System.out.println(listLinked);
}
private static void changeElement(
List list, String string, String replacement) {
if (list.contains(string)) {
// adding the replacement
list.add(list.indexOf(string), replacement);
// removing the unwanted
list.remove(string);
} else {
System.out.println("Element not found to replace");
}
}
Assuming your SimpleLinkedList implements the List interface and is at least Java 8:
private static void changeElement(
List<String> list, String string, String replacement) {
list.replaceAll(s -> s.equals(string) ? replacement : s);
}
Of course you could call this 'Util' method from your SimpleLinkedList passing itself as the first argument.
So I have been reviewing my data structures and came across an interesting thought regarding Java generics and the Object class. I have implemented and run a "generic bag" in two different ways (Notice below: IObjectBag.java, ObjectBag.java, IGenericBag.java, and GenericBag.java) and have used them both (Notice: Below main.java and Output). I have removed some of the unnecessary code as per stack overflow rules but if you want the full implementation, let me know.
Also, I have researched the topic in many websites, books and courses in addition to looking at the source code for the ArrayList class here and I understand that my GenericBag is a better option than my ObjectBag but not well enough to explain it in a practical way during an interview. And I am confused that my GenericBag uses more casting operations than my ObjectBag in its implementation (see Remove and PrintBag).
So, other than the syntactic sugar, why is my GenericBag better? Please use my classes as examples.
Are there any important differences in runtime/overhead/space/time I am not noticing?
How would you answer this question or expect it to be answered in an interview?
Bonus questions: If you want, please answer the bonus questions in the Main and GenericBag comments (I think I can answer them myself though, just want to hear your opinion).
IObjectBag interface:
public interface IObjectBag {
void add(Object item);
Object remove(Object item) throws NoSuchElementException;
boolean isEmpty();
int find(Object item);
Object get(int index);
int numItems();
}
ObjectBag class:
public class ObjectBag implements IObjectBag {
private Object [] items; // the java class attribute that will hold out "ints"
private int numItems;
public static void printBag(IObjectBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public ObjectBag(int size) {
this.items = new Object[size]; // fills array with null values
this.numItems = 0;
}
public void add(Object item){
// adds item to end of bag
}
public Object remove(Object item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
Object out = this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// return index given item or -1
}
public Object get(int index) {
// returns item given index
}
}
IGenericBag class:
public interface IGenericBag <T> {
void add(T item);
T remove(T item) throws NoSuchElementException;
boolean isEmpty();
int find(T item);
T get(int index);
}
GenericBag class:
public class GenericBag<T> implements IGenericBag<T> {
// private T[] items; can't use this b/c see comment in constructor
private Object[] items;
private int numItems;
public static void printBag(GenericBag bag) {
for(int i = 0; i < bag.numItems(); i++) {
System.out.println(bag.get(i));
}
}
public GenericBag(int size) {
// this.items = new T[size]; Bonus: throws generic array creation error (why?)
this.items = new Object[size];
this.numItems = 0;
}
public void add(T item){
this.items[this.numItems] = item;
this.numItems += 1;
}
public T remove(T item) {
int index = this.find(item);
if(index == -1) throw new NoSuchElementException("oops nothing found");
T out = (T) this.items[index];
this.items[index] = null;
this.numItems -= 1;
if(index + 1 != this.items.length && this.items[index + 1] != null) {
for(int i = index; i < this.items.length; i++) {
if(i + 1 != this.items.length) this.items[i] = this.items[i + 1];
}
this.items[this.items.length - 1] = null;
}
return out;
}
public int find(Object item) {
// given object return index or throw exception
}
public T get(int index) {
return (T) this.items[index];
}
}
Main class:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Hello StackOverFlow!");
Object int1 = new Integer(1);
Object int2 = new Integer(2);
Object int3 = new Integer(3);
/* using my object bag ************************************************/
System.out.println("using my object bag");
IObjectBag myObjectBag = new ObjectBag(3);
myObjectBag.add(int1);
myObjectBag.add(int2);
myObjectBag.add(int3);
myObjectBag.remove(int2);
ObjectBag.printBag(myObjectBag);
/* using my generic bag ***********************************************/
System.out.println("using generic bag");
// Bonus Question: using object like above causes error at add method (why?)
Integer int4 = new Integer(4);
Integer int5 = new Integer(5);
Integer int6 = new Integer(6);
GenericBag<Integer> myGenericBag = new GenericBag<Integer>(3);
//Bonus Question: using Interface decllaration like above causes error in print bag (why?)
myGenericBag.add(int4);
myGenericBag.add(int5);
myGenericBag.add(int6);
myGenericBag.remove(int4);
GenericBag.printBag(myGenericBag);
}
}
Output:
Hello StackOverFlow!
using my object bag
1
3
using generic bag
5
6
Problems with your ObjectBag that are 'automaticaly' solved by the type safety offered by your GenericBag implementation:
Accessing an entry returns Object, at this stage you do not know of what type Object is.
You can insert any types of Objects (mixed) e.g a String and an Integer into the same list, this is an anti pattern and causes non readable code (try it with your Generics bag!)
Because your compiler knows the type of your GenericBag after you have declared it, at any stage of your code if you hover over your genericBag instance you will know its type, this makes your code more readable and also extendable for other people
Generics also offer way more, imagine you want your GenericBag to only accept numbers, then you could write it as follows:
public class GenericBag<T extends Number>
My suggestion for you is to read some articles on Java basics and especially Generics, having a praxis based way of learning is a good thing, but there are plenty articles that can give you some very nice theoretical insight on the matter.
https://www.baeldung.com/java-generics
Reason of using, let's say, GenericBag<String> over ObjectBag is essentially the same as for using String (or any other type) over an Object:
Type safety.
You declare that some method returns a collection of Strings and nothing else, thus preventing yourself from putting there other objects, or trying to treat what you get from a bag as some other type. This might sound stupid when you have 100 lines of code, but this may save you lot of debugging time when you work with decent codebase.
Although, type safety is not a silver bullet, it is just an instrument, that some people find useful and some don't. I'm pretty sure it is a popular holywar topic for any programming forum.
If you feel comfortable working without this paradigm (Javascript background, right?), you might consider trying some dynamically typed language like Python instead of Java.
I'm pretty new to Java and I'm attempting to implement a Generic LinkedList Class in java. Below is the code yet it doesn't quite work right. I have some extra free time this semester and want to use this generic linkedlist to solve the linkedlist programming challenges in my interview test prep book. What am I doing wrong here? Why won't this work the way I want it to?
Thanks for the help in advance.
public class LinkedList {
public static linkedlist ll;
public static void main(String[] args) {
// TODO Auto-generated method stub
ll = new linkedlist();
Node one = new Node(1);
Node two = new Node(2);
Node three = new Node(3);
Node four = new Node(4);
System.out.println("s");
}
public static class linkedlist<T>{
public Node head;
public Node tail;
int size;
#SuppressWarnings("unchecked")
public linkedlist(){
size = 0;
}
void add(Class<T> typeParameterClass){
if(head == null){
head = new Node(typeParameterClass);
}
Node temp = new Node(typeParameterClass);
Node headCopy = head;
if(headCopy != null){
while(headCopy.getNext()!= null){
headCopy = headCopy.getNext();
}
headCopy.setNext(temp);
}
size++;
}
}
public static class Node<T>{
//final Class<T> typeParameterClass;
Class<T> value;
int intValue;
Node next = null ;
Node prev = null;
public Node(Class<T> typeParameterClass){
value = typeParameterClass;
}
public Node(int i) {
intValue = i;
// TODO Auto-generated constructor stub
}
public Node getNext() {
// TODO Auto-generated method stub
return next;
}
public Node getPrev() {
return prev;
}
public void setNext(Node temp){
next = temp;
}
}
}
You would first spent some reading about Java naming conventions. Class names start Uppercase; always; even for inner static classes. You would also avoid using too many inner static classes in the first place. In your example, there is absolutely no need to do it this way. You would rather put the methods that make up a LinkedList directly on the LinkedList class. You want that users of that class use that class; and not some inner static thing like LinkedList.linkedlist or LinkedList.Node.
You see, right now, your methods are all on the inner Node class. So, do you want to deal with Nodes each time when doing something about your List?!
Then you read about how generics work in general. Example:
Node one = new Node(1);
is probably not even compiling, but even when it does, it creates a raw type; as you do not have the type parameter there. You need something like:
Node<Integer> one = new Node<>(1);
instead - you have to tell the compiler what real type you want to use instead of that anonymous T.
In other words: start reading here. Right now, you have like 25% knowledge/understanding; and that is not enough to start coding.
That is about what can be said without further description from your side about "what is not working" in your code. And even then: as said; your code is on such a low scale of "understanding" that the only reasonable answer is: step back and learn about the things you want to use.
Going back over my basic ADT stuff here to revise for an interview, and trying to kill two birds with one stone by learning Java while I am. Attempting to write a simple algorithm for a merge sort with a generic linked list ( which I am creating myself). It's proving to be far more difficult than I had first imagined ! Can anyone help me out please ? I will start out working on the basics and will update this post as I get further in.
My code for the generic linked list is as follows :
public class NodeList<T extends Comparable<T> > {
private T head;
public NodeList<T> tail;
public NodeList( T item, NodeList<T> list ) {
head = item;
tail = list;
}
}
I am trying to access this class in another class I have made, which is as follows :
public class MyList<T extends Comparable<T>> {
private NodeList<T> nodes;
private static int size;
public MyList( ) {
nodes = null;
}
public MyList(T[] array ){
for( T item : array ) {
nodes = new NodeList<T>(item, nodes);
}
size = array.length;
}
public void add( T item ) {
nodes = new NodeList<T>( item, nodes );
size++;
}
public void addEnd( T item ) {
NodeList<T> temp = nodes;
while ( temp == null || temp.tail != null) {
temp = temp.tail;
}
size++;
temp.tail = new NodeList<T> ( item, null);
}
I believe, so far, everything to be correct up until the add and addEnd methods, which should add a generic to the start of the list and end of the list respectively.
My code continues with :
public static <S extends Comparable<S>>
MyList<S> sort( MyList<S> list ) {
if ( size > 1 ) {
MyList<S> left = leftHalf( list );
MyList<S> right = rightHalf( list );
list = merge( left, right );
}
return list;
}
private static <S extends Comparable<S>>
MyList<S> merge( MyList<S> left, MyList<S> right ) {
}
private static <S extends Comparable<S>>
MyList<S> leftHalf( MyList<S> list ) {
MyList <S> leftSide = new MyList();
int middle;
if(size % 2 == 1) {
middle = size +1;
} else {
middle = size;
}
for ( int countToMiddle = 0; countToMiddle < middle ; countToMiddle++ ) {
leftSide.addEnd(nodes);
}
// return elements from 0 .. list.size() / 2
}
And I get the error:
addEnd(S) in MyList cannot be applied to (NodeList)
which occurs when I run
leftSide.addEnd(nodes);
Can anyone see a reason for this/ tell me if I am correct up to this point of my work ? Thanks so much again!
If you want NodeList and MyList to only contain Comparable items,
you can replace the generic parameter T with something like:
public class NodeList<T extends Comparable> {
Or
public class NodeList<T extends Comparable<T>> {
And replace where you use Comparable with T. This way, you know T at least implements Comparable's methods.
Oracle's tutorials for generics should be able to help you with getting the hang of them.
One problem you may be having is that you refer to member variables from static functions, like in leftHalf you have:
for ( int countToMiddle = 0; countToMiddle < middle ; countToMiddle++ ) {
leftSide.addEnd(nodes);
}
nodes is a member variable, i.e. a non-static variable, so you can't call it from static methods. For that example, you'd have to get it from the passed MyList:
for ( int countToMiddle = 0; countToMiddle < middle ; countToMiddle++ ) {
leftSide.addEnd(list.nodes);
}
And the same goes for your other static methods that try to use member variables.
Also, the reason you are getting an error like: addEnd(S) in MyList<S> cannot be applied to (NodeList<T>) is because S is, according to your type parameter, a Comparable. NodeList does not extend Comparable!
The two solutions you have is
Make NodeList extend Comparable so you can pass it to MyList.addEnd
Make an overload (i.e. a different method with the same name) for addEnd that takes a NodeList, and add all the items in the passed NodeList to MyList
Or come up with a different solution that better fits the need of your classes.
While I realize you are implementing a linked list just to sharpen your skills for an interview (I wish you good luck!), I just want to add that there is a generified LinkedList already available in Java.
Why do you post almost the same question twice?
You could extend your question, add comments etc.
We already gave you that hint. :)
The error is happening because the class NodeList doesn't have a constructor that receives a generic T class and a NodeList.
Actually, this implementation will replace the reference object that nodes is referring on every loop. You should also fix that.
What you should do is put T to be a Comparable itself, and change the attribute, something like:
public class NodeList<T extends Comparable> {
private T head;
private NodeList tail;
public NodeList( T item, NodeList list ) {
head = item;
tail = list;
}
}
It would be better if you tell us what exactly the code is for.