java.lang.String cannot be cast to TreeComparable - java

TreeComparable is a Comparable interface.
The Error:
java.lang.String cannot be cast to TreeComparable
This is the line giving me the error
if (((TreeComparable) r.getInfo()).compareTo((TreeComparable) p.getInfo()) < 0 )
And here is the method for that line:
public void insertBST(Object o) {
ObjectTreeNode p, q;
ObjectTreeNode r = new ObjectTreeNode(o);
if (root == null)
root = r;
else {
p = root;
q = root;
while (q != null) {
p = q;
if (((TreeComparable)(r.getInfo())).compareTo((TreeComparable)(p.getInfo())) < 0 )
q = p.getLeft();
else
q = p.getRight();
}
if (((TreeComparable)(r.getInfo())).compareTo((TreeComparable)(p.getInfo())) < 0)
setLeftChild(p, r);
else
setRightChild(p, r);
}
}
Note: BST stands for binary search tree.
The getInfo method of the ObjectTreeNode class:
private Object info;
public Object getInfo() {
return info;
}
and finally, I don't know if these will help, but my TreeComparable compareTo declaration:
int compareTo(Object o);
and the compareTo method in the (Word) class:
String word;
public int compareTo(Object o) {
Word w = (Word) o;
return this.word.compareTo(w.getWord());
}
The Help is greatly appreciated.

This is because String does not implement the interface TreeComparable. There is a an interface Comparable that String implements. String can be upcasted to this interface.

Related

How to fix Unchecked cast warning in generic type casting [duplicate]

This question already has answers here:
How do I address unchecked cast warnings?
(22 answers)
Closed 8 months ago.
I'm implementing a list link in the stack. The program successfully passes all the required tests, but I encounter this warning. There is no disruption in the implementation of the program, but I am looking to eliminate this problem.
Can you tell me how to fix it by editing the code in the Equals method?
Unchecked cast: 'java.lang.Object' to 'LinkedStack'
public final class LinkedStack<E> implements Stack<E> {
private Node head = null;
private int size = 0;
#Override
public int size() {
return size;
}
#Override
public boolean isEmpty() {
return size == 0;
}
#Override
public void clear() {
head = null;
size = 0;
}
#Override
public boolean contains(E e) {
for (int i = 0; i < size; i++) {
E temp = pop();
if (temp.equals(e)) {
return true;
}
}
return false;
}
#Override
public E top() throws StackEmptyException {
if (size == 0) {
throw new StackEmptyException();
}
return head.element;
}
#Override
public void push(E e) {
head = new Node(e, head);
size++;
}
#Override
public E pop() throws StackEmptyException {
if (size == 0) {
throw new StackEmptyException();
}
E temp = head.element;
head = head.next;
size--;
return temp;
}
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
LinkedStack<E> that = (LinkedStack<E>) o;
if (that.size() != this.size()) return false;
Node j = that.head;
int counter = 0;
for (Node i = head; counter < size; i = i.next, j = j.next) {
if (i.element == null && j.element == null) {
counter++;
continue;
}
if ((i.element != null) && (j.element != null)) {
if (!i.element.equals(j.element)) {
return false;
}
} else {
return false;
}
counter++;
}
return true;
}
#Override
public int hashCode() {
int resultat = 1;
int counter = 0;
for (Node i = head; counter < size; i = i.next) {
if (i.element == null) {
counter++;
continue;
}
resultat = resultat * i.element.hashCode();
counter++;
}
return resultat;
}
protected class Node {
private final E element;
private final Node next;
protected Node(final E element, final Node next) {
this.element = element;
this.next = next;
}
}
}
I just realized you could in principle avoid explicitly casting to LinkedStack<E> and instead cast to LinkedStack<?>, since you check elements' equality separately down the line anyway.
As for the difference this makes - casting to LinkedStack<E> you assume that you're comparing this to a LinkedStack holding elements of the same type. The compiler can't check this assumption and warns about the unchecked cast. That could bring about a ClassCastException down the line if you handled the stack's elements as if they were of type E and they actually turned out to be some other type.
The wildcard generic <?> means you have no assumptions about the generic type of the particular LinkedStack you're working with, thus eliminating the warning.
That's what other answers to the "suppress unchecked cast warnings" mean when they say you'd best avoid unchecked casts unless absolutely necessary.
(I'm purposefully avoiding commenting on the rest of the provided code)

compareTo with objects returns a false while it is true

I am trying to check whether my levelorder of my Binary Search Tree is equal to the other one. To do this, I tried to make a compareTo method. I only give equal values to the method, but it keeps on saying the condition is false. When I place breakpoints, I see that the values are still equal. I am probably not understanding it correctly. Does anyone know how to solve this?
Here is what I did, as you can see below, the compareTo returns a 1 instead of a 0:
import edu.princeton.cs.algs4.BST;
import java.util.*;
public class MyBST implements Comparable<MyBST>{
private Object e;
public MyBST(Object e){
this.e = e;
}
private Object getE(){
return e;
}
public static void main(String[] args) {
int size = 4;
Random r = new Random();
Set<Integer> tes = new LinkedHashSet<>(size);
Stack<Integer> stack = new Stack<>();
while (tes.size() < size) {
tes.add(r.nextInt(10));
}
System.out.println("possible combinations");
Set<Stack<Integer>> combos = combos(tes, stack, tes.size());
Object[] arr = combos.toArray();
List<String> d = new ArrayList<>();
for (Object s : arr) {
String b = s.toString();
b = b.replaceAll("\\[", "").replaceAll("\\]", "");
d.add(b);
}
int index = 0;
do {
BST<String, Integer> bst1 = new BST<String, Integer>();
BST<String, Integer> bst2 = new BST<String, Integer>();
String key1 = d.get(index);
String key2 = d.get(index);
key1 = key1.replaceAll(" ", "");
String[] m = key1.split(",");
key2 = key2.replaceAll(" ", "");
String[] n = key2.split(",");
System.out.println("1e order");
for (int j = 0; j < m.length; j++) {
System.out.println(m[j]);
bst1.put(m[j], 0);
}
System.out.println("2e order");
for (int j = 0; j < n.length; j++) {
System.out.println(n[j]);
bst2.put(n[j], 0);
}
System.out.println("levelorder 1e BST");
MyBST e = new MyBST(bst1.levelOrder());
MyBST y = new MyBST(bst2.levelOrder());
System.out.println(bst1.levelOrder());
System.out.println("levelorder 2e BST");
System.out.println(bst2.levelOrder());
System.out.println(e.compareTo(y) + "\n");
index++;
} while (index < arr.length - 1);
}
public static Set<Stack<Integer>> combos(Set<Integer> items, Stack<Integer> stack, int size) {
Set<Stack<Integer>> set = new HashSet<>();
if (stack.size() == size) {
set.add((Stack) stack.clone());
}
Integer[] itemz = items.toArray(new Integer[0]);
for (Integer i : itemz) {
stack.push(i);
items.remove(i);
set.addAll(combos(items, stack, size));
items.add(stack.pop());
}
return set;
}
#Override
public int compareTo(MyBST o) {
if (this.e == o.e) {
return 0;
}
else
return 1;
}
}
Here you can find the BST.java class: BST.java
And the output is something like:
The breakpoint at the compareTo method says:
When you're using the == operator you're actually checking to see if the references point to the same object in memory. From your debugging screenshot you can see that they are not. this.e points to object Queue#817 while o.e points to Queue#819.
If all you want to do is test for equality, then just override equals and hashCode. You can do it like this (rest of class omitted):
public class MyBST {
private Object e;
public MyBST(Object e) {
this.e = e;
}
public Object getE(){
return e;
}
#Override
public int hashCode() {
return Objects.hashCode(e);
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MyBST))
return false;
MyBST me = (MyBST) obj;
if (e == null) {
if (me.e != null)
return false;
} else if (!e.equals(me.e))
return false;
return true;
}
}
Implementing Comparable is more involved since you need to check for less, equal, or greater than other instances of MyBST. Unfortunately, the only field in MyBST is an Object which does not tell you anything about its actual fields. So without specific fields with which to test you need to ensure that the Object you pass also implements Comparable. Then you can declare your class like this. Rest of class omitted.
It simply says that
MyBST is comparable.
And the object that is passed in the constructor is comparable.
class MyBST<T extends Comparable<? super T>> implements Comparable<MyBST<T>>{
private T e;
public MyBST(T e){
this.e = e;
}
public T getE(){
return e;
}
#Override
public int compareTo(MyBST<T> o) {
return e.compareTo(o.e);
}
}
The other alternative is to simply pass the actual object type and store it as such, not as Object. Then just implement Comparable in MyBST and use the appropriate fields of the passed object. Lets say the object was an Apple object, you could do this.
class Apple {
String type;
int weight;
}
class MyBST implements Comparable<MyBST> {
private Apple apple;
public MyBST(Apple apple) {
this.apple = apple;
}
#Override
public int compareTo(MyBST e) {
// this could be different depending on how you wanted
// to compare one apple to another. This comparison favors
// type over weight.
// check type - String class implements comparable
int ret = apple.type.compareTo(e.apple.type);
if (ret != 0) {
return ret;
}
// same type so check weight
if (apple.weight < e.apple.weight) {
return -1;
}
if (apple.weight > e.apple.weight) {
return 1;
}
return 0; // equals apples based on criteria
}
}
Finally, you have this.
private Object getE(){
return e;
}
A private getter is not usually very useful. Make it public.

Casting with Comparable

I'm trying to find the minimum value of a node within a tree, and in order to detect whether something has smaller value, I'm using the compareTo() function as seen below:
#SuppressWarnings("unchecked")
public static Object min(TreeNode t)
{
if(t == null) {
return null;
}
Comparable<TreeNode> min = (Comparable<TreeNode>) t;
if(t.getLeft() != null) {
Comparable<TreeNode> leftMin = (Comparable<TreeNode>) min(t.getLeft());
if( ((Comparable<TreeNode>)leftMin).compareTo( (Comparable<TreeNode>)min) < 0) {
min = leftMin;
}
}
if(t.getRight() != null) {
Comparable<TreeNode> rightMin = (Comparable<TreeNode>) min(t.getRight());
if( ((Comparable<TreeNode>)rightMin).compareTo( (Comparable<TreeNode>)min) < 0) {
min = rightMin;
}
}
return min;
}
However, I'm receiving the following error:
error: incompatible types: Comparable<TreeNode> cannot be converted to TreeNode
at the if statement.
I was told that the Object must be cast to Comparable in order to call compareTo()
And I have tried looking at this similiar question, but I don't have access to change the TreeNode Class
TreeNode Class:
public class TreeNode
{
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue)
{
value = initValue;
left = null;
right = null;
}
/*methods*/
}
And I have also tried: if(leftMin.compareTo(min) < 0) however that yields the same error.
Do you know how to properly cast and convert the following classes?
As suggested by others, you can use the comparable interface, which will require you to implement the compareTo method.
The compare to implementation details can be found in the java se docs:
Compares this object with the specified object for order. Returns a
negative integer, zero, or a positive integer as this object is less
than, equal to, or greater than the specified object.
So we can change your class to something like what is shown below (Note: I recommend converting value to an int or any other primitive type):
class TreeNode implements Comparable<TreeNode> {
// recommend to convert value to int or any other primitive type
private Object value;
private TreeNode left, right;
public TreeNode(Object initValue) {
value = initValue;
left = null;
right = null;
}
// if value is int, just use ==, < and >
// i.e. this.value == o.value, this.value < o.value and so on ...
#Override
public int compareTo(TreeNode o) {
if (this.value.equals(o.value)) return 0;
else if (this.value.hashCode() < o.value.hashCode()) return -1;
else return 1;
}
/*methods*/
}
Then you don't really need to do the casting in the min method. (Note: The implementation below is not actually correct - won't give you the min. It's just shown as to how the implementation would change after implementing the comparable interface).
// This method is not actually correct (i.e. won't actually find the min),
// but showing how it would change after using the comparable interface
// on the tree node class.
public TreeNode min(TreeNode t) {
if(t == null) {
return null;
}
TreeNode min = t;
if(t.getLeft() != null) {
TreeNode leftMin = min.getLeft();
if(leftMin.compareTo(min) < 0) {
min = leftMin;
}
}
if(t.getRight() != null) {
TreeNode rightMin = min.getRight();
if( rightMin.compareTo(min) < 0) {
min = rightMin;
}
}
return min;
}
The class TreeNode must implement the Comparable interface:
public class TreeNode implements Comparable<TreeNode> {
...
#Override
public int compareTo(TreeNode other) {
... // maybe compare 'initValue' here
}
}
also not sure if it is so good to cast TreeNode to Comparable, I would prefer to work
without casting at all (e.g. public static TreeNode min(TreeNode t))
Edit: probably it was meant to cast initValue to Comparable so it can be compared - not very (type-) safe having it declared as Object in that case.
Edit after question changed. Since TreeNode cannot be changed, I think you must clearly split nodes and values, probably something like below (must be completed):
public static TreeNode min(TreeNode node) {
...
TreeNode minNode = node;
Comparable<?> minValue = (Comparable<?>) minNode.getValue(); // guessed method name
if (node.getLeft() != null) {
TreeNode leftMin = min(t.getLeft());
Comparable<?> leftValue = (Comparable<?>) leftMin.getValue();
if (leftValue.compareTo(minValue) < 0) {
minNode = leftNode;
minValue = leftValue;
}
...
This requires that instances in Value implement Comparable.

binary search tree, insert method won't compile

I'm attempting to write my own binary search tree in java. I have written all my methods and I am now trying to write a program to test the methods.
However, when I try to implement my "insert" method, it will not compile and I have no idea why.
public class lab05driver {
public static void main(String[] args) {
BST q = new BST();
int a = 5;
String b = "jed";
double c = 1.8;
char d = 'r';
boolean e = false;
int f = 35;
String g = "yay";
double h = 2.1;
char i = 'i';
boolean j = true;
Integer k = 5;
q.insert(k);
}}
and my BST class looks like this:
public class BST implements myBST {
private myTreeNode root;
public BST() {
}
public void insert(Comparable x) {
if(root == null) {
root = new myTreeNode();
root.data = x;
} else if ( !lookup(x) ) {
root.insert(x);
}
}
...more code...
}
and, myBST looks like:
public interface myBST {
public void insert(Comparable x);
public void delete(Comparable x);
public boolean lookup(Comparable x);
public void printPreOrder();
public void printInOrder();
public void printPostOrder();
}
finally, myTreeNode looks like:
public class myTreeNode {
public myTreeNode() {
}
public Comparable data ;
public myTreeNode leftchild;
public myTreeNode rightchild;
public myTreeNode parent;
public void insert(Comparable d) {
//if less than
//does left exist? if it doesnt, make it, give it d
//if it exists call insertrecursive on rightchild
if(d.compareTo(data) <= 0) {
if(leftchild != null) {
leftchild.insert(d);
} else {
leftchild = new myTreeNode();
leftchild.data = d;
leftchild.parent = this;
}
} else {
if(rightchild != null) {
rightchild.insert(d);
} else {
rightchild = new myTreeNode();
rightchild.data = d;
rightchild.parent = this;
}
}
}
...more code...
}
it is throwing an error at "q.insert(k)" in the lab05driver. any help/suggestions would be greatly appreciated...
~~~~~
EDIT: sorry i jsut copied that wrong... there is a main method and Integer k is an integer...
the error im getting the command line is:
warning: [unchecked] unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable
q.insert(k); is a statement. Statements need to be in methods, it isn't currently in a method.
So do something like:
public class lab05driver
{
public static void main( String[] args )
{
BST q = new BST();
int a = 5;
String b = "jed";
double c = 1.8;
char d = 'r';
boolean e = false;
int f = 35;
String g = "yay";
double h = 2.1;
char i = 'i';
boolean j = true;
Integer k = 1; // changed because "Integer k = "test";" doesn't compile
q.insert(k);
}
}
Note the signature I used for the method. This is the signature that Java sees as the entry method (where the program will start).
The most obvious problem that I can see is:
Integer k = "test";
k needs to be an integer of some sort - you've assigned it a String. This is not a valid assignment. Valid values would be -1, 0, 1 etc - any integer value.
Once you assign a value value (or change k to be the String class) your code should be ok

HashMap in java cannot hash MyObject

I have defined a simple private class named SetOb which contains an int and a Set data structure. I have a HashMap in the 'main' method with SetOb as Key and Integer as value. Now as you can see in the main method, when I feed the HashMap with a SetOb instance and then look for an instance with exactly the same value, it returns 'null'. This has happened with me quite a few times before when I use my own defined data structures like SetOb as Key in HashMap. Can someone please point me what am I missing ?
Please note that in the constructor of SetOb class, I copy the Set passed as argument.
public class Solution {
public static Solution sample = new Solution();
private class SetOb {
public int last;
public Set<Integer> st;
public SetOb(int l , Set<Integer> si ){
last = l;
st = new HashSet<Integer>(si);
}
}
public static void main(String[] args) {
Map<SetOb, Integer> m = new HashMap< SetOb, Integer>();
Set<Integer> a = new HashSet<Integer>();
for(int i =0; i<10; i++){
a.add(i);
}
SetOb x = sample.new SetOb(100, a);
SetOb y = sample.new SetOb(100, a);
m.put(x,500);
Integer val = m.get(y);
if(val!= null) System.out.println("Success: " + val);
else System.out.println("Failure");
}
}
Your x and y are not the same object instances hence contains is not able to match y against x, which ends up not finding the matching key/value in the Map.
If you want the match to succeed, please implement(override) hasCode & equals method in SetOb which will compare the field values.
Sample methods(Eclipse generated) as below:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + last;
result = prime * result + ((st == null) ? 0 : st.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SetOb other = (SetOb) obj;
if (last != other.last)
return false;
if (st == null) {
if (other.st != null)
return false;
} else if (!st.equals(other.st))
return false;
return true;
}
The default implementation of hashCode uses object identity to determine the hash code. You will need to implement hashCode (and equals) in your private class if you want value identity. For instance:
private class SetOb {
public int last;
public Set<Integer> st;
public SetOb(int l , Set<Integer> si ){
last = l;
st = new HashSet<Integer>(si);
}
#Override
public boolean equals(Object other) {
if (other.class == SetOb.class) {
SetOb otherSetOb = (SetOb) other;
return otherSetOb.last == last && otherSetOb.st.equals(st);
}
return false;
}
#Override
public int hashCode() {
return 37 * last + st.hashCode();
}
}
SetOb needs to override the hashCode() and thus the equals() methods.
Hash-based collections use these methods to store (hashCode()) and retrieve (hashCode()) and equals()) your objects.

Categories

Resources