Extending vs. implementing Comparable in java [duplicate] - java

This question already has answers here:
What is PECS (Producer Extends Consumer Super)?
(16 answers)
Closed 4 years ago.
I'm trying to implement binary search tree in java. It can take any object as the data of a node in the tree, as long as that object implements the Comparable interface. This is needed because while putting a new node in the tree, we need to decide, whether the new node is of lesser or greater value compared to its parent. My Node class looks something like the following.
package com.java.ds.bst;
public class Node<T extends Comparable<T>> implements Comparable<T> {
private T data;
private Node<T> left = null;
private Node<T> right = null;
public Node() {
this.data = null;
}
public Node(T data) {
this.data = data;
}
public T getValue() {
return this.data;
}
public Node<T> getLeft() {
return this.left;
}
public Node<T> getRight() {
return this.right;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public void setRight(Node<T> right) {
this.right = right;
}
#Override
public int compareTo(T other) {
return this.data.compareTo(other);
}
}
What I don't understand is, in the class name declaration, why do I need T extends Comparable<T> instead of T implements Comparable<T>?

It is the syntax for generics, T extends Comparable<T> means it will accept anything that is Comparable<T>.
You are correct to use implements Comparable<T> when implementing the interface.

Related

Build Logic Tree like the where clause in sql

I want to build a Logic Tree in Java which contains the conditions that could be used
for database insertions.
for example:
Node tree = input0.eq(3).and(input1.eq(1).or(input2.greaterThan(5)));
could be converted to:
WHERE input0=3 AND (input1 = 1 OR input2 > 5)
Since a Node could be a logical expression like and,or etc. as well as a Leaf with data, I thought a parent Node class and two child classes, would be ideal. But I have no idea how to handle nested expressions. I already read a few similiar questions here, but they weren't really specific enough.
public class Node {
public Long id;
public Node parent;
public List<Node> children;
}
public class LogicalNode extends Node {
LogicType logicType;
public LogicalNode () {
super();
}
getter and setter...
}
public class LeafNode extends Node {
Object input;
public LeafNode () {
super();
}
getter and setter...
}
public enum LogicType
{
AND("and"),
OR("or"),
NOT("not"),
EQ("="),
GREATER_THAN(">"),
LESSER_THAN("<");
private String name;
LogicType (String name) {
this.name= name;
}
public String getName() {
return name;
}
}
To get you started, try something similar to this:
public abstract class Node {
abstract void toSql();
Node eq(Node other) {
return new LogicalNode(LogicalType.EQ, this, other);
}
...
}
public class LeafNode extends Node {
LeafNode(int value) {
this.value = value;
}
String toSql() {
return this.value.toString();
}
}
public class LogicalNode extends Node {
LogicalNode(LogicalType type, Node left, Node right) {
this.logicalType = type;
this.left = left;
this.right = right;
}
String toSql() {
return String.format(
"(%s) %s (%s)",
this.left.toSql(),
this.logicalType.getName(),
this.right.toSql()
);
}
}
The key here is that the LogicalNode is constructed using two other Nodes, but it doesn't concern itself with whether or not they are LeafNodes or LogicalNodes. All LogicalNode knows is that it has two things that can be converted to a string using toSql.

Java how to return a generic type that extends an interface

I have an interface named IDedObject and I am making a linkedlist class that uses generics that extend the IDedObject interface. In the linkedList class, I have a function that tries to find a given item based on it's data, and then returns that item. I am getting an error that says
Incompatible types. Required: AnyType. Found: IDedObject
This is what my code looks like:
Interface:
public interface IDedObject {
public int getID();
public void printID();
}
LinkedList:
public class singlyLinkedList<AnyType extends IDedObject> {
public Node<AnyType> endMarker;
public Node<AnyType> beginMarker;
AnyType findID(int ID){
Node curNode = beginMarker;
while(curNode.getNext() != endMarker){
if (curNode.getData().getID() == ID){
return curNode.getData();
}
}
return null;
}
}
class Node<AnyType extends IDedObject>{
public Node(AnyType d, Node<AnyType> n){
data = d;
next = n;
}
public Node getNext(){
return next;
}
public AnyType getData() {
return data;
}
public AnyType data;
private Node<AnyType> next;
private int theSize;
}
I appreciate any help with this. It's for a homework assignment, so i'm required to use a generic the extends IDedObject.
Thanks.
I fixed the problem by changing
Node curNode = beginMarker;
to
Node<AnyType> curNode = beginMarker;
in the findID function in the LinkedList class. Not sure how I missed that.

compareTo is asking me to cast, and I do not know why

Can someone explain why I am getting this error: The method compareTo(AVLNode) is undefined for the type AVLNode
Here is a shortened version of my Tree class:
public class AVLTree< E extends Comparable<E> >
{
private AVLNode<E> root ;
public AVLTree()
{
this.root = null;
}
public void insert ( AVLNode<E> item )
{
if( item.getLeft().compareTo(item.getItem() ) < 0) //ERROR IS HERE
{
}
}
}
Below is my a short version of my Node class
class AVLNode <E extends Comparable<E> >
{
private AVLNode<E> item;
private AVLNode<E> left;
public AVLNode ( AVLNode<E> item)
{
this.item = item;
this.left = null;
}
public AVLNode( AVLNode<E> item, AVLNode<E> lft )
{
this.item = item;
this.left = lft;
}
public AVLNode<E> getItem()
{
return this.item;
}
public AVLNode<E> getLeft()
{
return this.left;
}
}
Your Comparable base class assumes you're comparing to Es when you want to compare to AVLNode<E>s
So change it to inherit Comparable<AVLNode<E>> and see what happens.
Your AVLNode class should obviously look like this:
public class AVLNode<E extends Comparable<E>> {
private E item;
//...
public int compareTo(final E obj) {
return this.item.compareTo(obj);
}
Difference:
item should be of type E not AVLNode<E> because you want to store an E and not a AVLNode.
To state, that your AVLNodes are comparable, they could implement Comparable<T> themself by just delegating to E#compareTo() method:
public class AVLNode<E extends Comparable<E>> implements Comparable<AVLNode<E>> {
private E item;
//...
#Override
public int compareTo(final AVLNode<E> other) {
return this.item.compareTo(other.item);
}
}
getLeft() returns an AVLNode. You try and call getLeft().compareTo(...). This requires that AVLNode provides a matching method.
From this:
class AVLNode <E extends Comparable<E> >
{
private AVLNode<E> item;
...
It looks like your nodes can only hold other nodes. Presumably your items should actually be of the comparable type E. Then you can retrieve the item and call compareTo() on that.
That's because AVLNode doesn't have a method called compareTo() if you implement one then the issue should be solved.
You should also decide whether your want to compare E vs E or AVLNode vs AVLNode

Warning: The type parameter E is hiding the type E when using an inner class

I was writing a stack, one with a static Node and other non-static.
public class Stack<E> implements Iterable<E>
{
private int N;
private Node<E> first;
private static class Node<E> // This works fine.
{
private E item;
private Node<E> next;
}
}
But when I try to make the Node non-static, it gives me this warning "The type parameter E is hiding the type E"
public class Stack<E> implements Iterable<E>
{
private int N;
private Node<E> first;
private class Node<E> // This shows warning.
{
private E item;
private Node<E> next;
}
}
A bit of understanding which I have tell me that since static memeber is a member of class so it does not give me a warning but when I make it non-static it belongs to the instance. But its not a clear thought.
It's warning you that you are using the generic argument name E in a scope when it already is defined. Changing the generic argument name for Node would be one way to resolve the warning:
public class Stack<E> implements Iterable<E>
{
private int N;
private Node<E> first;
private class Node<T>
{
private T item;
private Node<T> next;
}
}
But since E is already exists, you should just use that; Node is already generic due to being defined within a generic type (Stack<object>.Node and Stack<String>.Node are different types):
public class Stack<E> implements Iterable<E>
{
private int N;
private Node first;
private class Node
{
private E item;
private Node next;
}
}
Note that this works because Node is not static, therefore it has a reference to the outer Stack<E> object, and because of this E must be defined. If Node is static then it has no real relationship to the outer Stack<E> type other than effectively being within its lexical scope.

Java Inheritance Maximize reuse

In following example, TreeNode is the superclass and BinaryNode is subclass.
public class TreeNode {
private int data;
private TreeNode parent;
private List<TreeNode> children;
TreeNode() {
this.data = 0;
this.parent = null;
this.children = new ArrayList<TreeNode>();
}
}
In subclass, every node has only two children.
I write as following.
How should I write the member fields and constructor to best use the superclass, yet keep the structure right?
public class BinaryNode extends TreeNode {
// int data;
// BinaryNode parent;
List<BinaryNode> children;
BinaryNode() {
super();
children = new ArrayList<BinaryNode>(2);
}
}
in constructor BinaryNode(), super() is called, what's the impact on children?
What's more, if the subclass has specific rules on some fields, like only two children in this sample, how to write the constructors in superclass and subclass to maximize reuse?
if I have the following method isLeaf() in superclass and don't write it in subclass.
When I try to use it with a subclass instance, would it function correctly?
public boolean isLeaf() {
if(this.children == null)
return true;
else
return false;
}
You mark the attributes protected in the superclass and the subclass should have access to them:
public class TreeNode {
protected int data;
protected TreeNode parent;
protected List<TreeNode> children;
...
public boolean isLeaf() {
if(this.children == null)
return true;
else
return false;
}
}

Categories