So guys I have to write a generic method to find the maximum element in a 2-D array then I have to test using integers, strings, and objects.
I'm a little sleep deprived so I apologize for what is probably a very very simple fix.
I have my generic method:
public class Generic {
public static <T extends Comparable<T>> T Max(T[][]stuff) {
T max = stuff[0][0];
for (int i = 0; i < stuff.length; i++)
for(int j = 0; j <stuff.length; i++)
if (stuff[i][j].compareTo(max) > 0)
max = stuff[i][j];
return max;
}
}
and simply trying to test with integers first
public class GenericTester {
public static void main(String[] args) {
Integer[][] myArray = { {0,1,2,3}, {3,2,1,0}, {3,5,6,1}, {3,8,3,4} };
System.out.println(Generic.Max(myArray));
}
}
Ok I fixed the previous error, dumb mistake, but yes now I am getting The method Max(T[][]) in the type Generic is not applicable for the arguments (int[][])
what would be the best fix for this problem?
Thanks for any and all help
Presumably you need Generic.Max(myArray) or else you need to
import static Generic.Max;
at the top of GenericTester.java.
Generics will not work with primitive types, so T cannot be bound to int. Note, in particular, that int does not extend Comparable<int>. You will need to use an Integer[][] array instead of int and similarly for the other primitive types.
EDIT In addition to the above, your loops need some work. First, the increment on the inner loop is wrong (this is why you are seeing an ArrayIndexOutOfBoundsException). Second, your code requires that the matrix is square and full (since you use stuff.length for the inner loop limit). Here's how I would write them (using enhanced for loop syntax):
public class Generic {
public static <T extends Comparable<T>> T Max(T[][]stuff) {
T max = stuff[0][0];
for (T[] row : stuff) {
for (T elt : row) {
if (elt.compareTo(max) > 0) {
max = elt;
}
}
}
return max;
}
}
For a truly general method, you would want to check that stuff[0][0] exists.
Related
There is a program which handles many lists of many types (Person, Cat, Chairs etc..).
The following code appears many times in the code. The code fills a given list with instances of type Cat until the list has a given number of instances.
int howMany = max - cats.size();
for(int i = 0; i < howMany; ++i) {
cats.add(new Cat());
}
Since this code appears many time we want to create a method to replace it. The method will accept the List that we want to add instances to and the max number of instances. It can accept more parameters if needed.
This seems simple at first but then I remembered it's not possible to write new T() because of type erasure.
What other way is there to achieve this?
You can re-use a method, that instantiates a class of a given type T.
public T getInstanceOfT(Class<T> aClass) {
return aClass.newInstance();
}
Then, you can implement a method, that populates a given List<T> with n objects of type T.
public <T> void populateList(List<T> list, Class<T> clazz, int n) {
for (int i = 0; i < n; i++) {
list.add(getInstanceOfT(clazz));
}
}
Note1: You have to handle IllegalAccessException and InstatiationException.
Note2: If you don't want to use getInstanceOfT() you can just do clazz.newInstance() when adding to the list.
You can use the method as follows:
int howMany = max - cats.size();
Class<Cat> catClass = Cat.class;
List<Cat> listOfCats = new ArrayList<Cat>();
populateList(listOfCats, Cats.class, howMany);
More info:
Create instance of Generic type in Java
Instead of adding all those unnecessary objects to the list, couldn't you wrap the shorter lists in an object that makes them look longer?
class PaddedList<T> extends AbstractList<T> implements List<T> {
private final List<T> wrappedList;
private final int size;
private final T padding;
public PaddedList(List<T> wrap, int size, T pad) {
this.wrappedList = wrap;
this.size = size;
this.padding = pad;
}
#Override
public T get(int index) {
return index < wrappedList.size() ? wrappedList.get(index) : padding;
}
#Override
public int size() {
return size;
}
}
public void test() {
List<String> test = Arrays.asList("One", "Two");
List<String> list10 = new PaddedList<>(test, 10, "Many");
System.out.println(list10);
}
this prints
[One, Two, Many, Many, Many, Many, Many, Many, Many, Many]
Obviously this will go very wrong if you try to modify any of the objects that are used as padding but if all you want is your lists seeming like they are fixed length then this would work very efficiently.
I have the following code:
public abstract class Heap {
Comparable<?> data[];
int count, size;
public Heap( int size ) {
this.size = size;
data = new Comparable<?>[ size + 1 ];
this.count = 0;
}
public abstract void insert( Comparable<?> item );
}
class MinHeap extends Heap {
public MinHeap (int size ) { super(size); }
public void insert( Comparable<?> item ) {
//this line here is giving me an error
//due to how I am storing the array in Heap
int k = data[ 0 ].compareTo( item );
}
}
The line indicated above is giving me this error: The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>). I cannot figure out a way to make it work while maintaining these conditions: 1) I want the MinHeap to work with any data that implements Comparable, 2) I do NOT want to pass a pre-initialized array into the constructor. I say this because I do not want to do the following:
abstract class Heap< T extends Comparable<T> > {
T data[];
public Heap( T data[], int size ) {
this.data = data;
//I do not want to have to pass an instantiated array.
//I want the constructor to handle the instantiation. If I do this I know the issue with the
//compareTo will be solved, but I really prefer to avoid this.
}
}
My question is this: In my code, why am I getting this error? Does anyone know a way besides the way that is described in the second example? I would like to be able to create a min heap data structure with any comparable data. All helpful comments are appreciated. Thank you.
Side note: do not worry about the access modifiers of the instance variables. I left them as default for simplicity. I do know that they should be private with setters/getters or protected.
First of all, this code is invalid for creating a generic array:
data = new Comparable<?>[ size + 1 ];
This link in the Java Trails explains why it's illegal, but it boils down to the fact that arrays must know their type at compilation, and generics work based off of type erasure and can be inferred at runtime.
But before we can fix that, there's an issue with your generics - they're not really...generic. You're only using the wildcard generic here with no bounds.
If you want to have your abstract class with a generic array that is full of Comparable, then you want to have your abstract class with a bound to Comparable<T>, and have your data simply be bound to T. With this, we can finally fix the array initialization into a compilable (but unchecked cast) form:
data = (T[]) new Comparable[size + 1];
Here's the full class for reference. It's close to your second form, and doesn't require that you pass in an instantiated array. Further, since T is bound to Comparable<T>, we don't need to declare it as an argument in the method - we can simply provide T.
public abstract class Heap<T extends Comparable<T>> {
T data[];
int count, size;
public Heap(int size) {
this.size = size;
data = (T[]) new Comparable[size+1];
this.count = 0;
}
public abstract void insert(T item);
}
Further to this example, you would also want to add the generic type to your subclass as well:
class MinHeap<T extends Comparable<T>> extends Heap<T>
Try this one:
First compareTo() return int not boolean value.
public abstract void insert( Comparable<?> item ); is wrong.
Use List in case of generic instead of static array. For more info read How to create a generic array?
Sample code:
abstract class Heap<T> {
List<Comparable<T>> data;
public Heap(int size) {
data = new ArrayList<Comparable<T>>();
}
public abstract void insert(T item);
}
class MinHeap<T extends Comparable<T>> extends Heap<T> {
public MinHeap(int size) {
super(size);
}
public void insert(T item) {
int k = data.get(0).compareTo(item);
}
}
Your data can contain any kind of object, as long as its class implements Comparable. So you could have Strings, Integers, Longs, or Bananas inside your array.
And comparing an Integer with a String or with a Banana doesn't make sense. That's why the compiler doesn't let you compile this code.
The second way is the right way. You can use an array of objects internally, and cast each object to a T. If all your methods only accept instances of T, then the casts are guaranteed to succeed. Or you can use a List instead, which is much more generic-friendly than arrays.
Hello fellow Stackoverflowers,
I have the following problem:
I have a situation, where I get an array of primitive numbers as an input. For example int[] or short[] or even byte[]. Now, I need to iterate over the code and do certain stuff, for example, write the numbers into a list. The problem is, however, that every type of number needs a certain list. No problem, I thought, and tried to use generics:
Object dataSet = provider.getDataArray();
Number[] copy = new Number[Array.getLength(dataSet)];
for(int i= 0; i < Array.getLength(dataSet); i++) {
copy[i] = (T) Array.get(dataSet, i);
}
This works beautifully. However, the problem is with performance. I know that is cannot be circumvented because Reflection and the occuring boxing of the primitives is costly. I am now searching for a pattern to reduce the amount of code, because writing
Object dataSet = provider.getDataArray();
Class<? extends Number> dataType = provider.getDataType();
Number[] copy = new Number[dataSet.length];
if(dataType == Float.class)
float[] dataSetAsFloat = (float[]) dataSet;
for(int i= 0; i < dataSet.length; i++)
copySet[i] = dataSetAsFloat[i];
else if (dataType == Double.class)
double[] dataSetAsDouble = (double[]) dataSet;
for(int i= 0; i < dataSet.length; i++)
copySet[i] = dataSetAsFloat[i];
....
is a very bloated solution, because the application in the program I'm writing is not as simple as shown here. Basically, I create several hundred lines of extra code because of this performance problem. Is there a solution to this? Perhaps a pattern I'm not aware of, or some really simple trick I'm not seeing?
I would be immensely grateful for a response.
Thanks.
Have you considered a strategy pattern that chooses a conversion strategy based on the data type? While it won't reduce much of the overall total code, it will help to modularize it.
public interface ArrayConversionStrategy<T extends Number> {
T[] convertArray
}
public class FloatConversionStrategy implements ArrayConversionStrategy<Float>
float[] convertArray(Object[] dataset) {
float[] dataSetAsFloat = new float[dataset.length];
for(int i= 0; i < dataSet.length; i++)
dataSetAsFloat [i] = dataset[i];
}
}
public class DoubleConversionStrategy { ... }
public class LongConversionStrategy { ... }
Then in the calling class have a map of data types to strategies
Map<Class<? extends Number>, ArrayConversionStrategy> map;
Object[] dataSet = provider.getDataArray();
Class<? extends Number> dataType = provider.getDataType();
ArrayConversionStrategy strategy = map.get(dataType)
return strategy.convertArray(dataSet);
Some of my generic syntax may be off here and may have some boxing/autounboxing that may need to be done, but just as a general strategy this may be useful.
Instead of unpacking the wrapper, you can use a getLong(int)/putLong for integers and getDouble(int)/putDouble for floating point. This will give you two methods which support all primitives types.
interface Array {
public long getLong(int idx);
public double getDouble(int idx);
public void setLong(int idx, long l);
public void setDouble(int idx, double d);
}
class ByteProvider implements Array {
}
class IntProvider implement Array {
etc.
Given the following definitions:
public enum SampleEnum1 { Uno, Dos, Tres }
public enum SampleEnum2 { One, Two, Three, Four }
I need two methods doing this:
Given the integer 2, return Dos if applied to SampleEnum1, Two if applied to SampleEnum2
Given the value One, return 1
In fact I need to translate an enumeration litteral into its sequence number in the enumeration definition, and vicae versa.
I don't mind using generics, reflexion, or whatever, as long as the same 2 methods work for any enumeration.
Do you have the solution?
Another approach is to use a helper method like
public static <E etxends Enum<E>> E lookup(Class<E> eClass, int number) {
return eClass.getEnumConstants()[number-1];
}
SampleEnum1 se1 = lookup(SampleEnum1.class, 2);
BTW: You could start with Zero which would simplify your code as well.
If you can be sure to keep your enums in order in the source file, you can do like this to get the enum by number:
public static SampleEnum1 getSpanishEnum(int index) {
return SampleEnum1.values()[index - 1];
}
public static SampleEnum2 getEnglishEnum(int index) {
return SampleEnum2.values()[index - 1];
}
And to go the other way, you can do a loop
public static <E extends Enum> getEnumIndex(E value, E[] values) {
for(int i = 0; i < values.length; i++) {
if(value == values[i]) {
return i + 1;
}
}
throw new NoSuchElementException();
}
calling it like this:
getEnumIndex(SampleEnum1.Dos, SampleEnum1.values());
The forward direction can be done using the Class.getEnumConstants() method:
public static <E extends Enum<E>> E getValue(Class<E> eClass, int index) {
return eClass.getEnumConstants()[index - 1];
}
Called as follows:
SampleEnum2 two = getValue(SampleEnum2.class, 2);
(Unfortunately, we can't write a generic method that uses the values() method that every enum has. It is static so we can't access it by polymorphic dispatching. To access it reflectively we'd need to know the actual class of E ... and that requires a Class<E> object. And if you have to pass that, you may as well call its getEnumConstants method.)
The reverse direction is simpler:
public static <E extends Enum<E>> int getIndex(E e) {
return e.ordinal() + 1;
}
Of course, it is much neater if you follow the normal IT convention that the indexes of a collection start from zero.
I have to pass a primitive 2d array to a filtering routine.The algorithm for filtering(median filter) is same irrespective of the type of the array.Is there a way to pass any type of array in a generic manner or should I overload the same same function with different array types.In the second case the same code will have to be repeated for different data types.
int[][] medianfilter(int[][] arr){ ... }
float[][] medianfilter(float[][] arr){ ... }
Is there a way to make the above code a generic one,instead of repeating the code for medianfilter in each an every overloaded function ?
There is no good way to do this for primitive arrays, which is why all the library functions (such as java.util.Arrays) also have these duplicated methods.
You could define a method
Object[] medianfilter(Object[] arr); // note the missing dimension
and use reflection to find out the runtime type. This is what System.arraycopy is doing. But you then need to type-cast. Ugly.
int[][] result = (int[][]) medianFilter( input );
Go with the duplicated methods.
There is a way to pass the type of an array in a generic manner:
public T test(T[][] arg)
{
T[][] q = arg;
T[] r = q[0];
T s = r[0];
return s;
}
... unfortunately it won't work for primitive types. You'll need to use Integer and Float as your parameterized types.
The only way to pass it in a generic manner and keep it as a primitive array is as an Object. Personally, I'd just overload it, and see it as a cost of using primitives.
To avoid duplication of code in the algorithm (if it is a lot of code) you could produce an abstract class called something like DoubleAlgorithm with abstract methods like double getElement(int i, int j) and handleResult(double result) and then write very small subclasses of this, one for each primitive type.
Let me explain with an example (suppose the algorithm was adding the numbers).
public int filter(int [][] values) {
IntAlgorithm algo = new IntAlgorithm(values);
algo.run();
return algo.getResult();
}
public double filter(double [][] values) {
DoubleAlgorithm algo = new DoubleAlgorithm(values);
algo.run();
return algo.getResult();
}
public class AbstractAlgorithm {
public run() {
double sum = 0.0;
for(int i=0; i<rows(); i++) {
for(int j=0; j<columns(i); j++) {
sum+=getElement(i, j);
}
}
handleResult(sum);
}
protected abstract int rows();
protected abstract int columns(int row);
protected abstract double getElement(int i, int j);
protected abstract void handleResult();
}
public class IntAlgorithm extends AbstractAlgorithm {
int [][] values;
int result;
IntAlgorithm(int [][] values) {
this.values= values;
}
public int rows() {
return values.length;
}
public int columns(int row) {
return values[row].length;
}
public double getElement(int i, int j) {
return values[i][j];
}
public void handleResult(double result) {
this.result = (int)result;
}
public int getResult() {
return result;
}
}
As you can see, it is quite verbose, but if your algorithm was big it might be worth it. Hopefully it is obvious how to extend to your algorithm.
As Thilo has pointed out, it isn't safe to do all algorithms with just treating ints/longs as doubles, but for a number it will be good enough. If it isn't for you, then you need to go even more verbose, work out which properties of numbers you need (eg add) and extract those to a separate interface. For a median filter, I would expect just using doubles will work fine, but I'd test the edge cases.