I've been trying to convert an Integer Wrapper class to int primitive class. I haven't yet found a proper way to make the code compile. I'm using Intellij IDEA, Java 11 Amazon Coretto, but I need to run it on a computer that runs java 8.
Here's the original code below:
static class Line<Integer> extends ArrayList<Integer> implements Comparable<Line<Integer>> {
#Override
public int compareTo(Line<Integer> other) {
int len = Math.min(this.size(), other.size());
for (int i = 0; i < len; i++) {;
if ((int) this.get(i) != (int) other.get(i)) {
if ((int this.get(i) < (int) this.get(i)) {
return -1;
} else if ((int) this.get(i) > (int)this.get(i)) {
return 1;
} else {}
}
}
...
note that the Line is inserted to an ArrayList.
Originally I used forced casting on all the Integer objects so it'll be like (int) this.get(i). It worked on my local terminal and my Intellij wasn't bothered about it, but unfortunately not the other computer. It couldn't compile there
I thought it was because of the forced casting, since the other computer returned
Main.java:159: error: incompatible types: Integer cannot be converted to int
if ((int) this.get(i) != (int) other.get(i)) {
^
where Integer is a type-variable:
Integer extends Object declared in class Line
so I deleted them all and thought I could let the machine unbox the Integer wrapper on its own. It still didn't compile.
If the code is left like what's written above (no forced casting), it will return "Operator '<' not applicable for 'Integer', 'Integer'"
So I used the .compareTo() method. Compile error.
Then I tried to assign them to an int variable. Intellij IDEA was screaming at me that it required int but found Integer instead. So I force-casted, like so
int thisLine = (int) this.get(i);
int otherLine = (int) other.get(i);
if (thisLine != otherLine) {
if (thisLine < otherLine) {
return -1;
} else if (thisLine > otherLine) {
return 1;
} else {}
Nope, didn't work. Removing the cast also didn't work.
I looked up the Javadocs (https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html#intValue--) this time about the Integer class and found a promising little method called intValue(). Problem is? Intellij cannot resolve that method (oddly, VSCode does not consider this an error). I used it like this
int thisLine = this.get(i).intValue();
int otherLine = other.get(i).intValue();
if (this.get(i) != other.get(i)) {
if (thisLine < otherLine) {
return -1;
} else if (thisLine > otherLine) {
return 1;
and sure enough, another compile error on that stubborn computer.
I'm running out of options. I'm seriously considering creating a new custom class just so I can store int values in an ArrayList without having to deal with all this Java backwards incompatibility nonsense.
Anyone here know a consistent method for converting an Integer wrapper object to an int primitive object in Java?
This is the clue in the error message that explains it:
where Integer is a type-variable:
Integer extends Object declared in class Line
Integer is not java.lang.Integer but a type variable with a confusing name...
You declared the type variable here:
static class Line<Integer> extends ArrayList<Integer> implements Comparable<Line<Integer>>
It's as if you declared it like this:
static class Line<T> extends ArrayList<T> implements Comparable<Line<T>>
but by naming the type variable Integer instead of T, and then you try to cast objects of the type T to int later on.
Fix it by not declaring a type parameter named Integer, you don't need that here:
static class Line extends ArrayList<Integer> implements Comparable<Line<Integer>>
You shouldn't have to cast an Integer to an int at all. Integer class has .compareTo methods which compare two integers.
A 0 means value1 is equal to value2. -1 is value1 is less than value2 and a 1 is value1 is greater than value2.
Try the following:
public int compareTo(Line<Integer> other) {
//get the smallest length
int len = this.size() <= other.size() ? this.size() : other.size();
for (int i = 0; i < len; i++) {
int compare = this.get(i).compareTo(other.get(i));
if (compare != 0) { //if compare is not zero they are not the same value
return compare;
}
}
//If we get here, everything in both lists are the same up to "len"
return 0;
}
The compareTo() method is a method of Integer class under java. lang
package. ... It returns the result of the value 0 if Integer is equal
to the argument Integer, a value less than 0 if Integer is less than
the argument Integer and a value greater than 0 if Integer is greater
than the argument Integer.
In you class "Integer" is not a java.lang.Integer but a Generic class that is the reason
Related
I dont know if the functionality of my code is the correct one for binary search BUT this is not my question, I want to solve it myself.
My problem is in testing its functionality while I get the following errors:
I really dont know how to solve this issue. Please help me!
My code:
public class BinarySearchGeneric<T extends Comparable<T>>{
public int search(T[] array, T element){
int start = 0;
int end = array.length - 1;
int mid = (start + end) / 2;
while(!element.equals(array[mid]) && end != 0) {
if (element.equals(array[mid])) {
return mid;
} else if (array[mid].compareTo(element) < 0) {
end = mid - 1;
mid = (start + end) / 2;
} else if(array[mid].compareTo(element) > 0){
start = mid + 1;
mid = (start + end) / 2;
}
}
return -1;
}
}
Main Method:
public class Main {
public static void main(String[] args) {
int[] a = {1,2,3,4,5,6,7,8,9,10};
BinarySearchGeneric binarySearchGeneric = new BinarySearchGeneric(a);
System.out.println("BinarySearch Generic: " + binarySearchGeneric.search(a, 8));
}
}
There are two compilation issues here:
There is no constructor of BinarySearchGeneric which takes a parameter, but you're trying to pass the parameter. Remove it:
BinarySearchGeneric binarySearchGeneric = new BinarySearchGeneric();
int[] is not an acceptable parameter to a generic method expecting an array, because int is a primitive type, not a reference type, and so can't be used in generics. The solution is simply to declare an array of Integer, rather than int:
Integer[] a = {1,2,3,4,5,6,7,8,9,10};
The compiler converts these int literals to Integer instances automatically.
But there are more issues.
You're declaring a variable of raw type. This basically switches off the compiler's type checking associated with that variable, making it likely that you will make a type error. Add the generic parameters:
BinarySearchGeneric<Integer> binarySearchGeneric = new BinarySearchGeneric<>();
Arrays and generics don't really play well together. Things would start get a bit messy if you declared a generic, comparable class:
class GenericComparable<T> extends Comparable<T> { ... }
and then tried to declare an array of GenericComparables to pass to binarySearchGeneric, since you can't directly create a generic array.
It's much easier simply to avoid arrays, and use a List<T> instead:
public int search(List<T> array, T element){
Potentially, you have inconsistent behaviour, because you are mixing equals and compareTo in the search. Whilst compareTo should be consistent with equals (in the sense that a.compareTo(b) <=> a.equals(b), it isn't necessarily true.
You can make the behaviour consistent by only using compareTo:
int c = array[mid].compareTo(element);
if (c == 0) {
// ...
} else if (c < 0) {
// ...
} else {
// ...
}
I don't see a user defined constructor for the BinarySearchGeneric class, so your code should look something like this:
BinarySearchGeneric binarySearchGeneric = new BinarySearchGeneric();
System.out.println("BinarySearch Genetic: ", binarySearchGeneric(a, 8));
I want to generate a binary tree with key - value pairs in their nodes.
In my binary tree I want to implement nodes at the beginning with an insert method, which implements a new left node if the key is smaller than the key of the current node. Then if there is already a left node it will check again for it. The same logic follows for right/greater node inserts.
I wrote my code first using the int type because it's way easier for me to test my code before I use generics (new topic for me). It worked when using int but I an unsure how to compare two generics with themselves by using "<" or ">".
public ListCell<Type> checkKey(Type key, ListCell<Type> checkCell) {
ListCell<Type> newCell = null;
if (key < checkCell.key && checkCell.left != null) {
...
}
...
}
I don't know if it's worth saying but I'm creating my binary tree with a selfcoded list.
Above you can see my current checks but i can't compare my given key now with checkCell.key because of them not being numbers.
So my general question is how to compare the keys in generics if they are "smaller" or "greater" than the other for my implementation in a binary tree.
Thanks in advance
You would need to ensure that your generic type implemented the Comparable interface, and then use the compareTo method instead. Java does not support overloading the > operator (or any operator overloading, for that matter).
As per the documents, compareTo:
Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
An example (that you'll have to map on to your exact code), assuming that key is your item you will store in your node, and checkCell.key is your node
int compareResult = key.compareTo(checkCell.key);
if (key < 0) { // it goes on the left }
else if (key == 0) { // it is the same }
else { // it goes on the right }
In your compareTo method you need to decide what fields in your class determine it's "ordering". For example, if you have a size and priority field, you might do:
#Override public int compareTo(Type other) {
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (this == other) return EQUAL;
if (this.size < other.size) return BEFORE;
else if (this.size > other.size) return AFTER;
else { // size is equal, so test priority
if (this.priority < other.priority) return BEFORE;
else if (this.priority > other.priority) return AFTER;
}
return EQUAL;
}
Bounded type parameters are key to the implementation of generic algorithms. Consider the following method that counts the number of elements in an array T[] that are greater than a specified element elem.
public static <T> int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e > elem) // compiler error
++count;
return count;
}
The implementation of the method is straightforward, but it does not compile because the greater than operator (>) applies only to primitive types such as short, int, double, long, float, byte, and char. You cannot use the > operator to compare objects. To fix the problem, use a type parameter bounded by the Comparable<T> interface:
public interface Comparable<T> {
public int compareTo(T o);
}
The resulting code will be:
public static <T extends Comparable<T>> int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray)
if (e.compareTo(elem) > 0)
++count;
return count;
}
bounded type parameters
I have a question: I work in environment of Eclipse.
Sometimes the computer does not give to the following casting:
int a ...
Object ans = (int) a;
But only this conversion:
int a ...
Object ans = (Integer) a;
I understand why you can do the casting between Object to Integer, but why primitive variable - there are times when you can, and there are times you can not do a casting?
Thank you
I am attaching the code which the compiler not let me make casting between int variable to object:
/** #return minimum element */
public Object minimum(){
return minimum(this.root);
}
public Object minimum(BSTNode node){
if (node.left != null) return minimum(node.left);
return node.data;
}
/** #return maximum element */
public Object maximum(){
return maximum(this.root);
}
public Object maximum(BSTNode node){
if (node.right != null) return maximum(node.right);
return node.data;
}
public Object findNearestSmall(Object elem) {
int diff;
diff = (int)maximum() - (int)minimum();
if (compare(minimum(), elem) == 0) return elem;
else return findNearestSmall(elem, this.root, diff);
}
public Object findNearestSmall(Object elem, BSTNode node, int mindiff){
if(node == null) return (int)elem - mindiff;
int diff = (int)elem - (int)node.data;
if(diff > 0 && mindiff > diff) mindiff = diff;
/* Case 2 : Look for in left subtree */
if(compare(node.data, elem)>-1)
return findNearestSmall(elem, node.left, mindiff);
else
/* Case 3 : Look for in right subtree */
return findNearestSmall(elem, node.right, mindiff);
}
Before Java 1.5, you couldn't even do this:
int a;
...
Object x = (Integer) a;
The compiler would complain that a is of a primitive data type, and therefore cannot be cast to an object.
Starting with Java 1.5, Java introduced the concept of automatic boxing. So, the following became OK:
int a;
...
Object x = (Integer) a;
Because the compiler knows how to convert from a primitive int to the boxed type Integer automatically; and from Integer to an Object it's, well, not a problem.
However, what you're trying to do:
int a;
...
Object x = (int) a;
Is basically telling the compiler to avoid boxing. You explicitly tell the compiler to leave a as an int, and put a reference to that int into an Object. The compiler isn't designed to deal with such a case.
You cannot cast from a referenced data-type to a primitive data-type i.e. you cannot:
Object x = (int)a;
You can however do:
Object x = (Integer)a;
because Integer is a class and int is a primitive data-type.
If I assume it correctly, the functionality you want to achieve is get the integer's value from Object x which can be done as:
Object x = (Integer)a;
//Do something and somewhere else
int z = ((Integer)x).intValue();
This may through a ClassCastException if it is not of Integer class.
You should look into the difference between int which is a primitive type, and Integer, which is a wrapper class in Java.
An Integer is also an Object and stays as an Object on the Heap.
An int is a primitive type. It is NOT an Object. An Object has its own state and behavioral properties, int doesn't have those. So you get a compilation error when trying to convert an Object to a primitive. On the other hand, Converting an int to Object is possible because of Autoboxing
But I am able to execute the following code. I am using jdk 1.6 and the following code is not throwing me any errors or runtime exceptions.
int i=5;
Object test = (int)i;
System.out.println(test.getClass());
Output: class java.lang.Integer
int is a primitive type.
Way of declaration: int a = 5;
Integer is a wrapper class (it extends Object).
Way of declaration: Integer a = new Integer(5);
When you write
Integer a = 5;
compiler automatically converts it to
Integer a = new Integer(5);
This feature is called Autoboxing (since Java 5.0)
int can not be casted to Object as it is not a referenced data type (object) at all.
But it can be casted to other primitive types.
On the other hand, Integer can be casted to Object.
When you write
Object ans = (Integer) a;
compiler does autoboxing and then casts it.
Object ans = (int) a;
gives a compiler error because the cast to int is successful, but it can not be assigned to an Object reference.
Hope this helps.
Good luck.
T get(int i) {
if (i < 0 || i > n - 1) throw new IndexOutOfBoundsException();
return a[i];
}
T set(int i, T x) {
if (i < 0 || i > n - 1) throw new IndexOutOfBoundsException();
T y = a[i];
a[i] = x;
return y;
}
I'm looking over some coding examples from my textbook, but they never mention what T is. I'm not sure how to search about this since I don't know what it's called or it's purpose.
I was wondering if someone can show me a write-up or some info about this. Thank you
T represents an object type using generics.
Whatever type x is in the set call, the set method will return that same type. In the get call, the return type is T, too. That type must be defined somewhere else, probably in the type of the class, where it might show up as <T>.
So if this is a class that is some sort of collections (since it is dealing with indexes), it might be defined as:
public class SomeCollection<T> {
Then it might get instantiated like:
SomeCollection<String> arr = new SomeCollection<String>();
In that case, T would be String, and the return type of the get and set methods, and the type of set parameter x, would all be String.
If it gets instantiated like:
SomeCollection<Integer> arr = new SomeCollection<Integer>();
then T is an Integer.
You could have both in the same code, without having to write two (or more) different versions of SomeCollection.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java: Array of primitive data types does not autobox
I've been doing some Java lately (mostly as a recap on what I did at university as my current job doesn't involve any Java at all) and one thing that never got introduced to us properly is Generics.
I've been doing the Generics tutorial on the Oracle Java website and I've been stumped by the following example that I modified a bit:
public static <Integer extends Comparable<Integer>> int countGreaterThan(Integer [] anArray, Integer elem) {
int count = 0;
for (Integer e : anArray)
if (e.compareTo(elem) > 0)
++count;
return count;
}
And I use this method to compare an Integer array with the following Integer:
Integer [] numarr = {1, 2, 3, 4 , 5};
Integer num = new Integer(5);
int count = Util.countGreaterThan(arrnum, num);
This seems to work fine, however if I pass a primitive array and a primitive int, it doesn't:
int [] arrnum = {1, 2, 3, 4 , 5};
int othernum = 3;
int count = Util.countGreaterThan(arrnum, othernum);
The compiler complains with:
method countGreaterThan in class Generics.Util
cannot be applied to given types;
required: Integer[],Integer
found: int[],int
reason: no instance(s) of type variable(s)
Integer exist so that argument type int conforms to formal parameter type Integer
The tutorials seemed to be pretty adamant that Java will always autobox/unbox objects and primitives as necessary and yet it won't do it in this particular case, what am I missing?
Also what could be a good way to generalise this comparing method as much as possible? If I used T instead of Integer, then it would look for a T object, rather than whatever I pass to it.
I apologise if the post is confusing and if I seem pretty ignorant about the stuff I talk about above, it's just that I've been working primarily as a perl programmer (and not as particularly experienced one either) and generalising there seems as less of an issue (due to the lack of type enforcement).
Thanks in advance!
The code below seems to work as far as I can see:
public static <Integer extends Comparable<Integer>> int countGreaterThan(Integer [] anArray, Integer elem) {
int count = 0;
for (Integer e : anArray) {
if (e.compareTo(elem) > 0)
++count;
return count;
}
although I get a warning "The type parameter Integer is hiding the type Integer". See #ErichSchreiner's answer for an explanation of why auto-boxing won't work here.
A good generalisation of your method would be:
public static <T extends Comparable<? super T>> int countGreaterThan(T[] anArray, T elem) {
int count = 0;
for (T e : anArray) {
if (e.compareTo(elem) > 0) {
++count;
}
}
return count;
}
All you really care about is that anArray has the same type of elements as elem is, and that it is comparable to it's own type.
Your declaration of countGreaterThan() hides the built-in type Integer. To clarify, consider the slightly modified version:
public static <I extends Comparable<I>> int countGreaterThan(I [] anArray, I elem) {
int count = 0;
for (I e : anArray)
if (e.compareTo(elem) > 0)
++count;
return count;
}
Now it should become apparent that your second attempt at calling can not work as there can be no autoboxing done. For generics to work, you need to supply objects, not primitives.