I had an interview days ago and was thrown a question like this.
Q: Reverse a linked list. Following code is given:
public class ReverseList {
interface NodeList {
int getItem();
NodeList nextNode();
}
void reverse(NodeList node) {
}
public static void main(String[] args) {
}
}
I was confused because I did not know an interface object could be used as a method parameter. The interviewer explained a little bit but I am still not sure about this. Could somebody enlighten me?
This is in fact one of the most common and useful ways to use an interface. The interface defines a contract, and your code can work with any class that implements the interface, without having to know the concrete class - it can even work with classes that didn't exist yet when the code was written.
There are many examples in the Java standard API, especially in the collections framework. For example, Collections.sort() can sort anything that implements the List interface (not just ArrayList or LinkedList, though implementing your own List is uncommon) and whose contents implement the Comparable interface (not just String or the numerical wrapper classes - and having your own class implement Comparable for that purpose is quite common).
It's not the interface "object" being passed to the method, still just a regular object. It's just a way of saying "this parameter will accept any object that supports this interface". It's equivalent to accepting some object of a base class type, even if you're passing in a subclass.
This is called programming to interfaces. You don't code to a specific implementation class of node lists but to the interface implemented by all those implementations.
That way your code will still work if someone writes a new and much better implementation of NodeList after you wrote your reverse method and you don't have to adapt your code for each new implementation of NodeList.
The argument needs an object, which class implements an interface (the parameter).
In pseudo Java the code:
void reverse(NodeList node) {
// your code
}
is equal to:
reverse(x) {
if(x == null || x instanceof NodeList) {
// your code
}else throw new RuntimeException("Some sort of error.");
}
Note; read more on Interfaces here: http://java.sun.com/docs/books/tutorial/java/IandI/interfaceAsType.html
This is one possible implementation:
public class ReverseList {
interface NodeList {
int getItem();
NodeList nextNode();
}
static class Node implements NodeList {
private int item;
private Node next;
#Override
public int getItem() {
return item;
}
public void setItem(int si) {
item = si;
}
#Override
public NodeList nextNode() {
return this.next;
}
public void setNext(Node n) {this.next=n;}
}
Node reverse(NodeList head) {
Node node = (Node) head;
Node previous = null;
while(node.nextNode() !=null) {
Node tempNext = (Node) node.nextNode();
node.setNext(previous);
previous = node;
node = tempNext;
}
node.setNext(previous);
return node;
}
public static void main(String[] args) {
//Initialization block
ReverseList rl = new ReverseList();
Node n1= new Node(); n1.setItem(1);
Node n2=new Node(); n2.setItem(2);
Node n3 =new Node(); n3.setItem(3);
n1.setNext(n2); n2.setNext(n3); n3.setNext(null);
//Reversing the list
System.out.println("Before reversal");
System.out.println(n1.getItem() +"->"
+ n1.nextNode().getItem() + "->"
+ n1.nextNode().nextNode().getItem() + "->"
+n1.nextNode().nextNode().nextNode());
rl.reverse(n1);
System.out.println("\nAfter reversal");
System.out.println(n3.getItem() +"->"
+ n3.nextNode().getItem() + "->"
+ n3.nextNode().nextNode().getItem() + "->"
+n3.nextNode().nextNode().nextNode());
}
}
Program output:
Before reversal
1->2->3->null
After reversal
3->2->1->null
I am very curious to know if this problem can be solved by using an anonymous class. Any ideas?
Had this same confusion while learning lambda stuff.
This video didnt explain the concept, but it's a clear way for you to see how it works in terms of passing an interface as a parameter.
https://www.youtube.com/watch?v=mk3erzL70yM
The major benefit of using interfaces, IMHO, is being able to test easily. Suppose you have an interface called, PatientManager.
You can write specific unit tests for imaginable things like "CachingPatientManager" or "LDAPPatientManager", the use case could be myriad.
The benefit is because the programming to interface becomes highly reusable and testable.
You cannot create an instance (/object ) of an Interface.
Yes, you can pass Interface as a parameter in the function. But the question seems incomplete. Interface isn't implemented by any class. Something is missing. If you try to run this, compiler will not show any error.
But, in the reverse() method you need to create an instance of class that implements NodeList interface. I hope this makes sense.
Related
I need a doubly linked list that can work on different node implementations. Note that I do not want nodes that contain generic data, like DoublyLinkedNode<T>, but something like DoublyLinkedList<N extends DoublyLinkedNode<T>>.
To be precise, I use the list in the general case with standard nodes, but in other parts of my program I need nodes with additional fields. So I implemented the general node as
public class DoublyLinkedNode<T> {
DoublyLinkedNode<T> before, after;
T value;
}
and the special type as
public class DoublyLinkedSpecialNode<T, S> extends DoublyLinkedNode<T> {
S specialValue;
}
Now in my DoublyLinkedList implementation I want to be able to handle both cases at one, because all the code basically fiddles around with the pointers that are obviously common to both implementations.
This gives a few requirements:
1) When I use the special node, I want to be able to return it as the DoublyLinkedSpecialNode type to be able to access the additional fields.
2) The list must use a DoublyLinkedNode type to access the pointers of the nodes.
3) The list is assigning the pointed-to nodes to other nodes, e.g. head = node.after;, so the type of the pointers in the special node must be the same as the type in the list.
Extending the list makes no sense because then I could not change the return type of the methods. Therefore I tried two ideas without success:
The already mentioned solution: Generic node type that extends from DLN
The list would look like this:
public class DoublyLinkedList<T, N extends DoublyLinkedNode<T>> {
N head, tail;
N tail() {
return tail; // OK
}
void remove(N node) {
if (head == node) {
head = node.after; // Type error
}
...
This solution conflicts with requirement 3), because in the list the type is an N that extends from DLN, but in the node implementation N the pointer is of the type of the base class/interface DLN (the pointer type could theoretically be more general than N).
Base DLN instead of generics
In this case the list works on the base class node and accepts the subclasses because of polymorphism:
public class DoublyLinkedList<T> {
DoublyLinkedNode<T> head, tail;
DoublyLinkedNode<T> tail() {
return tail;
}
void remove(DoublyLinkedNode<T> node) {
if (head == node) {
head = node.after; // OK
}
...
But tail() can only return nodes as the general type, conflicting with 1). I would prefer not to use casting, because I assume it's bad practice (?) but also because the implementation is performance critical. There surely is a better way?
I found another solution that is okay-ish, not very performant but more elegant than the last solution.
The idea ist to use only one type of nodes, and wrap the varying content in a generic container. The DLN code looks like this:
public class DoublyLinkedNode<C> {
DoublyLinkedNode<C> before, after;
C content;
public static class ValueContent<T> {
T value;
}
public static class ValueSpecialContent<T, S> extends ValueContent<T> {
S specialValue;
}
}
The list implementation then looks something like this:
public class DoublyLinkedList<C> {
DoublyLinkedNode<C> head, tail;
public DoublyLinkedNode<C> head() {
return head;
}
void remove(DoublyLinkedNode<C> node) {
if (head == node) {
head = node.after;
...
And I can access the special field from the calling class like this:
DoublyLinkedList<SpecialContent<SpecialType>> list;
SpecialType s = list.head().content.specialValue;
There is some overhead because each node has to instantiate that container class, but I think it's still better than casting. I have to check the performance impact.
The following Java code is valid - no compile- or run-time errors.
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<>("hello", 5).areEqual()
);
}
private static class Comparator<T> {
private final T left;
private final T right;
public Comparator(T left, T right) {
this.left = left;
this.right = right;
}
public boolean areEqual() {
return left.equals(right);
}
}
}
I expect the values "hello" and 5 are casted to Object, which is a common parent.
Is there a way to write the class in such a way that passing other than objects of the same type causes a compile-time error? I.e. passing objects casted to a common ancestor not allowed.
Not really, no.
Because your generic type is unbound, there's only one common ancestor: Object - as you correctly surmise.
The only thing you can realistically do in this scenario is ensure that equals is correctly defined for objects you want to pass through this method. You would also want to handle cases in which you pass null as an argument, too.
Just specify the type in the generic parameters...
public class Test {
public static void main(String[] args) {
System.out.println(
new Comparator<String>("hello", 1).areEqual()
);
}
...
}
If you do this with your current code, you will get a compiler error.
When you leave it unspecified, Java does not bother doing any type checking and simply uses the super type (Object) as the type for both.
You will also find the same issue when you do something like:
System.out.println(Arrays.asList("hello", 1)); // Will compile
vs
System.out.println(Arrays.<String>asList("hello", 1)); // Will not compile
So, I think it is not possible by using generic. But you can restrict it by checking the Object type in the constructor like below code.
public Comparator(T left, T right) {
if(left.getClass()!=right.getClass()) {
throw new IllegalArgumentException("All values passed needs to be object of same class");
}
this.left = left;
this.right = right;
}
However, this will not give you compile time error but it will through Exception when a different type of object passed to the constructor.
As #Makoto already answered, the short answer is no.
If you look at code snippet for equals method in your favorite IDE then you'll see that it has line like if (getClass() != another.getClass()) return false; It means that you check class of object inside equals. You could do the same at areEqual method but probably it's not needed - it should be implemented on another level
I need to create a myStack class and then use it to test for Palindromes... I chose to create an ArrayList based implementation of the stack.
import java.util.ArrayList;
public class myStack<AnyType>{
private ArrayList<AnyType> arr;
public myStack(ArrayList<AnyType> a){
arr = a;
}
public void push(AnyType element) {
arr.add(element);
}
public AnyType pop() {
if(arr.size() == 0)
{
System.out.println("Stack Underflow");
return null;
}
else
{
AnyType element = arr.get(arr.size() -1);
arr.remove(element);
return element;
}
}
public AnyType top() {
if(arr.size() == 0)
{
System.out.println("Stack Underflow");
return null;
}
else
return(arr.get(arr.size() -1));
}
}
Then I use it in a class called Palindrome (not complete yet)
However, when I compile, it tells me
"Note: Palindrome.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details."
When I comment out the line myStack m = new myStack(test);
It compiles, so I know this is the problem... Why would the myStack class be the problem? Is it something to do with the "AnyType" I used in the stack class?
Your class myStack. is generic with the template type <AnyType> and is currently using a Raw Type (hence the warning). Please follow Java naming conventions, and rename it MyStack. Then, use it with a type (and in Java 7 and up the diamond operator <>) -
// myStack m = new myStack(test);
myStack<Character> m = new myStack<>(); // <-- Please use MyStack.
if you intend to use MyStack class for any of the type, you can use the wildcard "?".
So your MyStack will be unbounded wildcard type generic class, and therefore hold anything.
Ill add a little perspective.. not answering the question directly..
What does stack have to do with palindrome?
Generics is slightly-advanced/optional concept. There are more important things to learn first. So, fix it if you want.. but you can also ignore the warning.
I would prefer to split the program into 3 aspects - (a) method to check if a single string is palindrome (b) method to read lines in a file (c) method to check if a string contains only digits and numbers
Write separate methods to achieve each of them and get the best quality of code, for example by referring stackoverflow for each
Wire them up together to get the final program working
IMHO... Java is vast and you need to consciously postpone learning stuff like Generics.
Focus on these:
Object oriented design - You could write a StringUtil and add a
static method like checkPalindrome
Variable and class naming convention (Java developers follow conventions almost to last letter)
I will suggest a structure for your program:
Your main class should be named as FilePalindromeChecker
Create a StringUtil class with a static method to check for palindrome:
public static boolean checkPalindrome
Have another static method in StringUtil to check for alphanumeric: public
static boolean checkPalindrome
Happy coding!
Let´s say I have a method that inserts a number into a Binary Tree
public BinaryNode insert(Comparable x, BinaryNode t) {
//Logic here
}
BinaryTree t = new BinaryTree();
How would I cast a number , for example 4 to match the right paremeters on this methods? Ex.
t.insert(4, t ) // I know this wont work, but I wanted to to something like this
It should work fine - it'll be boxed into an integer. Sample code:
public class Test {
static void foo(Comparable<?> c) {
System.out.println(c.getClass());
}
public static void main(String args[]) throws Exception {
foo(10);
}
}
This works even if you use the raw type Comparable, although I'd recommend against that.
Admittedly I strongly suspect that you'd be better off making your BinaryNode (and presumably BinaryTree) class generic, at which point you'd have:
// You shouldn't need to pass in the node - the tree should find it...
BinaryTree<Integer> tree = new BinaryTree<Integer>();
tree.insert(10);
It should work if you pass new Integer(4) instead of 4 assuming you are using Java version prior to 5 (as you are saying it's not working).
I am trying to using the compareTo method for a generic Node type E.
I have already bound E to Comparable
public class LinkedList<E extends Comparable<E>> {
// ----------------------------------------------------------
// Implementing the doubly linked nodes (static nested class)
// ----------------------------------------------------------
private static class Node<E extends Comparable<E>> {
This method isSorted is implemented within the LinkedList class, the Node class is within the Linkedlist class.
I keep getting a compilation error "The method compareTo(LinkedList.Node) is undefined for the type LinkedList.Node"
I believe that only pops up when E is not extending Comparable, in my case it is.
Any help?
public boolean isSorted( ){
if(!isEmpty()){
Node<E> temp = head;
boolean local = true;
int x=0;
while (temp.next != null){
x=temp.compareTo(temp.next);
if(x<0){
temp = temp.next;}
else {return local;}
}
return local;}
else{ throw new IllegalArgumentException();}
}
I checked this thread already, How to compare generic nodes in a linked list using Comparable?
It didn't help.
Thank you in advance
Mjall2
You're trying to compare the nodes, when it's only the values inside the nodes that are Comparable. Instead of temp.compareTo(temp.next), you probably want something like temp.value.compareTo(temp.next.value).